Chapter3 集合的线程不安全问题
3.1 ArrayList
- 举例说明其线程不安全
报错:public static void main(String[] args) { List<String> list = new ArrayList<>(); for (int i = 0; i < 300; i++) { new Thread(()->{ list.add(UUID.randomUUID().toString().substring(0,8)); System.out.println(list); }, String.valueOf(i)).start(); } }
ConcurrentModificationException(并发修改异常)
- 解决方法
- 使用
Vector
代替ArrayList
:Vector使用了synchronsized - 使用
Collections
工具类:List<String> list = Collections.synchronizedList(new ArrayList<>());
- 使用
CopyOnWriteArrayList
代替ArrayList
:List<String> list = new CopyOnWriteArrayList();
- 使用
3.2 HashSet
- 举例说明其线程不安全
public static void main(String[] args) { Set<String> set = new HashSet<>(); for (int i = 0; i < 300; i++) { new Thread(()->{ set.add(UUID.randomUUID().toString().substring(0,8)); System.out.println(set); }, String.valueOf(i)).start(); } }
Hashset
底层为HashMap
,value
为常量。 - 解决方法
- 使用
Collections
工具类:Set<String> set = Collections.synchronizedSet(new HashSet<>());
- 使用
CopyOnWriteArraySet
代替HashSet
:Set<String> set = new CopyOnWriteArraySet();
- 使用
3.3 HashMap
- 举例说明其不安全
public static void main(String[] args) { Map<String,String> map = new java.util.HashMap(); for (int i = 0; i < 300; i++) { new Thread(()->{ map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0, 8)); System.out.println(map); }).start(); } }
- 解决方法
- Map<String,String> map = new ConcurrentHashMap<>();