HashSet不安全
HashSet也是线程不安全的,底层没有进行任何线程同步处理。
在hashset的源码中,底层是用hashmap实现的:
每次add的时候,把值放在了map对象中的key,而map对象的value则全部统一放一个常量:
在下面的demo中,hashset在多线程情况下和arrayList一样会抛出java.util.ConcurrentModificationException
/** * @author zkw * @Description HashSet不安全 */ public class ThreadHashSet { public static void main(String[] args) { Set<String> list = new HashSet<>(); for (int i = 0; i < 30; i++) { new Thread(()->{ list.add(UUID.randomUUID().toString().substring(0,8)); System.out.println(list); }, i+"").start(); } } }
解决方法 使用 CopyOnWriteArraySet
public class ThreadHashSet { public static void main(String[] args) { Set<String> list = new CopyOnWriteArraySet<>(); for (int i = 0; i < 30; i++) { new Thread(()->{ list.add(UUID.randomUUID().toString().substring(0,8)); System.out.println(list); }, i+"").start(); } } }
HashMap不安全
使用HashMap空参构造,其初始容量是16,负载因子0.75
初始容量和负载因子都可以自定义,构造方法如下:
HashMap同上面两个类一样,在多线程情况下会出现并发修改异常java.util.ConcurrentModificationException
解决方法:使用ConcurrentHashMap
public static void main(String[] args) { Map<String,String> list = new ConcurrentHashMap<>(); for (int i = 0; i < 30; i++) { new Thread(()->{ list.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0,8)); System.out.println(list); }, i+"").start(); } }