目录
一、异常演示
循环创建线程,将数据放入集合的同时,从集合中读取数据。
/**
* list集合线程不安全问题
*/
public class ThreadDemo04 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 30; i++) {
new Thread(()->{
//向集合中添加内容
list.add(UUID.randomUUID().toString().substring(0, 8));
//从集合中获取内容
System.out.println(list);
}, String.valueOf(i)).start();
}
}
}
运行结果:
出现了并发修改异常
那么如何解决呢?
二、解决方案
1、vector
直接将ArrayList替换为Vector即可
// List<String> list = new ArrayList<>();
List<String> list = new Vector<>();
运行结果:
为什么会这样呢?vector和ArrayList有什么不同呢?
进入Vector的源码可以发现,里面几乎所有的方法都加了synchronized关键字
这样确实可以避免线程安全问题,不过效率比较低。
2、Collections工具类
使用Collections工具类中的synchronizedList()方法生成线程安全的集合。
// List<String> list = new ArrayList<>();
// List<String> list = new Vector<>();
List<String> list = Collections.synchronizedList(new ArrayList<>());
运行结果:
看一下jdk1.8的API对他的介绍:
3、CopyOnWriteArrayList 写时复制技术
// List<String> list = new ArrayList<>();
// List<String> list = new Vector<>();
// List<String> list = Collections.synchronizedList(new ArrayList<>());
List<String> list = new CopyOnWriteArrayList<>();
运行结果:
三、写时复制技术
1 、特性
它相当于线程安全的 ArrayList。和 ArrayList 一样,它是个可变数组;但是和 ArrayList 不同的时,它具有以下特性:
1、它最适合于具有以下特征的应用程序:List 大小通常保持很小,只读操作远多于可变操作,需要在遍历期间防止线程间的冲突。
2、 它是线程安全的。
3、 因为通常需要复制整个基础数组,所以可变操作(add()、set() 和 remove() 等等)的开销很大。
4、 迭代器支持 hasNext(), next()等不可变操作,但不支持可变 remove()等操作。
5、 使用迭代器进行遍历的速度很快,并且不会与其他线程发生冲突。在构造迭代器时,迭代器依赖于不变的数组快照。
2、原理
写时复制技术中,读操作支持并发读,即多个线程可以同时读到集合内的元素。写操作是独立写,当一个写线程执行写操作时,所有其他写线程阻塞;当该线程写的时候,将原集合中的数据复制一份,在拷贝的集合中完成写操作后,再将该拷贝集合和原集合合并。
为什么需要拷贝,在原数组直接修改不行吗?这篇文章讲得很清楚:CopyOnWriteArrayList写时复制的原理_Endwas的博客-CSDN博客
最后我们来看一下源码:
public 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();
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/124915.html