暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Java多线程进阶(二八)—— J.U.C之collections框架:CopyOnWriteArraySet

TPVLOG 2021-06-21
228

本文首发于Ressmix个人站点:https://www.tpvlog.com

一、CopyOnWriteArraySet简介

CopyOnWriteArraySet
,是另一类适合并发环境的SET工具类,也是在JDK1.5时,随着J.U.C包一起引入的。 我们之前已经介绍过了ConcurrentSkipListSet,ConcurrentSkipListSet底层基于Skip List(跳表)实现,其操作平均时间复杂度均为 O(logn)

CopyOnWriteArraySet,从名字上可以看出,也是基于“写时复制”的思想。事实上,CopyOnWriteArraySet内部引用了一个 CopyOnWriteArrayList
对象,以“组合”方式,委托CopyOnWriteArrayList对象实现了所有API功能。

  1. public class CopyOnWriteArraySet<E> extends AbstractSet<E>

  2. implements java.io.Serializable {


  3. private final CopyOnWriteArrayList<E> al;


  4. /**

  5. * Creates an empty set.

  6. */

  7. public CopyOnWriteArraySet() {

  8. al = new CopyOnWriteArrayList<E>();

  9. }


  10. public CopyOnWriteArraySet(Collection<? extends E> c) {

  11. if (c.getClass() == CopyOnWriteArraySet.class) {

  12. CopyOnWriteArraySet<E> cc = (CopyOnWriteArraySet<E>) c;

  13. al = new CopyOnWriteArrayList<E>(cc.al);

  14. } else {

  15. al = new CopyOnWriteArrayList<E>();

  16. al.addAllAbsent(c);

  17. }

  18. }

  19. // ...

  20. }

二、CopyOnWriteArraySet原理

我们来看下CopyOnWriteArraySet是如何实现API接口的功能的:

  1. public int size() {

  2. return al.size();

  3. }


  4. public boolean isEmpty() {

  5. return al.isEmpty();

  6. }


  7. public boolean contains(Object o) {

  8. return al.contains(o);

  9. }


  10. public Object[] toArray() {

  11. return al.toArray();

  12. }


  13. public <T> T[] toArray(T[] a) {

  14. return al.toArray(a);

  15. }


  16. public void clear() {

  17. al.clear();

  18. }


  19. public boolean remove(Object o) {

  20. return al.remove(o);

  21. }


  22. public boolean add(E e) {

  23. return al.addIfAbsent(e);

  24. }


  25. public boolean containsAll(Collection<?> c) {

  26. return al.containsAll(c);

  27. }


  28. public boolean addAll(Collection<? extends E> c) {

  29. return al.addAllAbsent(c) > 0;

  30. }


  31. public boolean removeAll(Collection<?> c) {

  32. return al.removeAll(c);

  33. }


  34. public boolean retainAll(Collection<?> c) {

  35. return al.retainAll(c);

  36. }


  37. public Iterator<E> iterator() {

  38. return al.iterator();

  39. }



  40. public boolean removeIf(Predicate<? super E> filter) {

  41. return al.removeIf(filter);

  42. }


  43. public void forEach(Consumer<? super E> action) {

  44. al.forEach(action);

  45. }

可以看到,上述所有的方法都是通过委托实现的,唯一的区别就是CopyOnWriteArraySet不允许含有重复元素,所以添加元素( add
方法)时,内部调用了CopyOnWriteArrayList的 addAllAbsent
方法。

三、总结

既然CopyOnWriteArraySet也是基于“写时复制”的思想,那么它的特性也和CopyOnWriteArrayList是类似的,归结起来,有以下几点:

  1. 适合“读多写少”且数据量不大的场景。

  2. 线程安全

  3. 内存的使用较多

  4. 迭代是对快照进行的,不会抛出 ConcurrentModificationException
    ,且迭代过程中不支持修改操作。


文章转载自TPVLOG,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论