java创建线程安全的Set集合

CopyOnWriteArraySet

CopyOnWriteArraySet<String> copyOnWriteArraySet = new CopyOnWriteArraySet<>();
原理

和CopyOnWriteArrayList实现原理一样,采用读写分离的并发策略,读操作的时候不加锁,写操作时创建底层数据的新副本,在新副本上执行写操作,写操作结束后将原引用指向新的容器。适合读多写少的场景。

特点
  • 读操作性能高
  • 当使用迭代器遍历时,在遍历的间隔中如果修改了集合,不会抛出ConcurrentModificationException异常。
  • 由于要复制新副本,会占用较大内存
  • 写操作时在新的副本上操作,此时的读操作还是在旧副本上,所以无法保证实时性
  • 大量写操作性能很差

Collections.synchronizedSet()

HashSet<String> hashSet = new HashSet<>();
Set<String> synchronizedSet = Collections.synchronizedSet(hashSet);
原理

在原先Set的每一个方法上都加上synchronized关键字

特点
  • 性能较差
  • 遍历间隔中如果修改了集合,仍会抛出异常ConcurrentModificationExceptions

Collections.newSetFromMap()

Set<String> setFromMap = Collections.newSetFromMap(new ConcurrentHashMap<>());
原理

封装了ConcurrentHashMap,利用ConcurrentHashMap的性质确保生成的Set是线程安全的。

特点
  • 该方法必须传入一个空的map
  • 性能较好,ConcurrentHashMap是分区的,写操作时对应的分区时是synchronized的,读操作与其他读操作、写操作是完全并发的(但可能没法看到当前正在写入的更改的结果)
  • 迭代器创建后可能会看到变化,也可能看不到变化,而且批量操作不是原子操作
  • reSize操作较慢,因此在初始化时最好能够指定大小(3/4满时就会reSize)
  • 需要hashCode()方法有较好的性能
  • 不允许再和传入的map做交互

ConcurrentHashMap.newKeySet()

ConcurrentHashMap.KeySetView<String, Boolean> keySetView = ConcurrentHashMap.newKeySet();
原理

jdk1.8以后引入的特性,是ConcurrentHashMap的特性的一部分

特点
  • 与上面提到的Collections.newSetFromMap(new ConcurrentHashMap<>())相似

你可能感兴趣的:(java,java,set,并发编程,线程安全)