什么是CopyOnWriteArrayList?
opyOnWriteArrayList
CopyOnWrite (简称:COw):即先复制再写入,就是在添加元素的时候,先把原List列表复制一份,再添加新的元素。
先来看下它的add方法源码:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } }
添加元素时,先加锁,再进行复制替换操作,最后再释放锁。
再来看下它的get方法源码:
复制代码
1
2
3
4
5
6
7
8private E get(Object[] a, int index) { return (E) a[index]; } public E get(int index) { return get(getArray(), index); }
可以看到,获取元素并没有加锁。
这样做的好处是,在高并发情况下,读取元素时就不用加锁,写数据时才加锁,大大提升了读取性能。
CopyOnWriteArraySet
CopyOnWriteArraySet逻辑就更简单了,就是使用CopyOnWriteArrayList的 addlfAbsent方法来去重的,添加元素的时候判断对象是否已经存在,不存在才添加进集合。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30public boolean addIfAbsent(E e) { Object[] snapshot = getArray(); return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false : addIfAbsent(e, snapshot); } private boolean addIfAbsent(E e, Object[] snapshot) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] current = getArray(); int len = current.length; if (snapshot != current) { // Optimize for lost race to another addXXX operation int common = Math.min(snapshot.length, len); for (int i = 0; i < common; i++) if (current[i] != snapshot[i] && eq(e, current[i])) return false; if (indexOf(e, current, common, len) >= 0) return false; } Object[] newElements = Arrays.copyOf(current, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } }
这两种并发集合,只适合于读多写少的情况,如果写多读少,使用这个就没意义了,因为每次写操作都要进行集合内存复制,性能开销很大,如果集合较大,很容易造成内存溢出。
最后
以上就是自由导师最近收集整理的关于【什么是CopyOnWriteArrayList?】的全部内容,更多相关【什么是CopyOnWriteArrayList内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复