Java
来源:互联网 发布:熊族软件下载 编辑:程序博客网 时间:2024/05/29 18:10
CopyOnWrite容器
java 1.5 提供了写时复制容器,比如:CopyOnWriteArrayList和CopyOnWriteArraySet等。
CopyOnWriteArrayList
CopyOnWriteArrayList是java.util.ArrayList一种线程安全的变体,所有的写操作(add, set 等等)会重新刷新底层数组。CopyOnWriteArrayList底层使用了重入锁,这是有代价的,但是当遍历操作远远超过修改操作时,它可能比其他方式更高效,当你不想同步遍历的时候也是非常有用的。
例子
这个例子总多个线程对ArrayList进行写操作,会抛出异常。如果将ArrayList改为CopyOnWriteArrayList就不会抛异常。
public class Demo { private static List<String> list = new ArrayList<>(); public static void main(String[] args) { for (int i = 0; i < 1000; i++) { new Thread(new WriteThread()).start(); } } static class WriteThread implements Runnable { @Override public void run() { for (int i = 0; i < 1000; i++) { list.add(Thread.currentThread().getName() + i); } } }}
输出:
Exception in thread "Thread-0" Exception in thread "Thread-2" java.lang.ArrayIndexOutOfBoundsException: 73 at java.util.ArrayList.add(ArrayList.java:459) at com.study.guava.copyonwrite.Demo$WriteThread.run(Demo.java:25) at java.lang.Thread.run(Thread.java:745)java.lang.ArrayIndexOutOfBoundsException: 366 at java.util.ArrayList.add(ArrayList.java:459) at com.study.guava.copyonwrite.Demo$WriteThread.run(Demo.java:25) at java.lang.Thread.run(Thread.java:745)Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: 4164 at java.util.ArrayList.add(ArrayList.java:459) at com.study.guava.copyonwrite.Demo$WriteThread.run(Demo.java:25) at java.lang.Thread.run(Thread.java:745)
概念
CopyOnWrite容器即写时复制的容器,往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器的底层数组复制出一份,然后往新的数组中添加元素,最后将新的数组再赋值回给容器的底层数组。
add
public boolean add(E e) { //CopyOnWriteArrayList属性可重入锁 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(); } }
remove
private boolean remove(Object o, Object[] snapshot, int index) { final ReentrantLock lock = this.lock; //加锁 lock.lock(); try { //获取底层数组 Object[] current = getArray(); int len = current.length; //找到要移除对象的索引 if (snapshot != current) findIndex: { int prefix = Math.min(index, len); for (int i = 0; i < prefix; i++) { if (current[i] != snapshot[i] && eq(o, current[i])) { index = i; break findIndex; } } if (index >= len) return false; if (current[index] == o) break findIndex; index = indexOf(o, current, index, len); if (index < 0) return false; } //将原数组以移除对象索引为分界,复制到新数组 Object[] newElements = new Object[len - 1]; System.arraycopy(current, 0, newElements, 0, index); System.arraycopy(current, index + 1, newElements, index, len - index - 1); //将新数组赋值给底层数组 setArray(newElements); return true; } finally { //释放锁 lock.unlock(); } }
阅读全文
0 0
- java
- JAVA
- JAVA
- JAVA
- java
- Java
- Java
- JAVA:
- java
- java
- java
- java
- Java
- java
- java
- java
- JAVA?
- java
- 从零开始前端学习[2]:img标签的使用
- 如何将matlab中的imresize()函数移植到python中
- ndk学习笔记C语言文件加解密
- MYSQL基础命令
- 真机同步到电脑桌面鼠标操作
- Java
- 两个栈实现一个队列
- 图像特征提取三大法宝:HOG特征,LBP特征,Haar特征
- 机器学习----学习笔记
- 指向下一个节点
- windows下安装tensorflow的简单方法
- 混淆遇到无法找到文件aapt_rules.txt
- 内部接口
- Leetcode [Longest Substring Without Repeating Characters]