JAVA集合类:
java.util包下的HashSet和HashMap类不是线程安全的,
java.util.concurrent包下的ConcurrentHashMap类是线程安全的。java
写2个测试类来验证下:安全
package com.cdfive.learn.thread; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** * 验证HashSet不是线程安全 * * @author cdfive * @date 2019-02-11 */ public class HashSetTest { public static void main(String[] args) { final Set<Integer> set = new HashSet<>();// 结果可能大于1000 // final Set<Integer> set = Collections.synchronizedSet(new HashSet<>());// 结果等于1000 // final Set<Integer> set = Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>());// 结果等于1000 // 往set写入1-1000 Runnable runnable = new Runnable() { @Override public void run() { for (int i = 1; i <= 1000; i++) { set.add(i); } } }; int threadNum = 10;// 线程数 List<Thread> threadList = new ArrayList<>(); for (int i = 0; i < threadNum; i++) { Thread thread = new Thread(runnable); threadList.add(thread); thread.start(); } // 主线程等待子线程执行完成 for (Thread thread : threadList) { try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(set.size());// 结果可能大于1000 } }
package com.cdfive.learn.thread; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * 验证HashMap不是线程安全 * * @author cdfive * @date 2019-02-11 */ public class HashMapTest { public static void main(String[] args) { final Map<Integer, Integer> map = new HashMap<>();// 结果可能大于1000 // final Map<Integer, Integer> map = Collections.synchronizedMap(new HashMap<>());// 结果等于1000 // final Map<Integer, Integer> map = new ConcurrentHashMap<>();// 结果等于1000 // 往map写入1-1000, key和value相同 Runnable runnable = new Runnable() { @Override public void run() { for (int i = 1; i <= 1000; i++) { map.put(i, i); } } }; int threadNum = 2;// 线程数 List<Thread> threadList = new ArrayList<>(); for (int i = 0; i < threadNum; i++) { Thread thread = new Thread(runnable); threadList.add(thread); thread.start(); } // 主线程等待子线程执行完成 for (Thread thread : threadList) { try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(map.size());// 结果可能大于1000 } }
若是须要保证线程安全的场景:
1.将HashSet或HashMap转换为线程安全,使用Collections.synchronizedSet或Collections.synchronizedMap方法;
2.使用Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>())或使用java.util.concurrent包下的ConcurrentHashMap;
3.仍然使用HashSet或HashMap,使用时手动进行加锁或同步;// 考虑到尽量提高性能ide
在项目中根据实际场景进行选择和应用。性能