- 问题说明
- List集合三种解决方案
- Vector
- Collections
- CopyOnWriteArrayList
- Set集合的解决方法
jdk中修改集合(如List, Set等)的方法都没有使用synchronize关键字, 在线程使用直接调用这些方法会产生线程安全问题(即同时访问数据会出错), 所以称这些类/接口是线程不安全的
比如下面执行ArrayList的add方法(线程不安全的):
public class ListAdd{
private static final List<Integer> list = new ArrayList<>();
public static void main(String[] args){
for(int i = 0; i < 10; i ++){
new Thread(() -> {
list.add(1);
System.out.println(list);
}, "AAA").start();
new Thread(() -> {
list.add(2);
System.out.println(list);
}, "BBB").start();
}
}
}
结果有可能(也不一定)出现ConcurrentModificationException(并发修改)异常
List集合三种解决方案 Vector来自jdk1.0古老的实现类, 在修改集合的方法(其他方法不需要使用)中使用了synchronize关键字
用Vector代替ArrayList,可以实现线程安全, 但是效率实在是太低了, 所以没啥人用
private static final List<Integer> list = new Vector<>();
Collections
另一个古老的解决方法, 和第一个意思差不多, 用另一种方法取代ArrayList(用的也少):
private static final List<Integer> list = Collections.synchronizedList(new ArrayList<>());
CopyOnWriteArrayList其实前面两种方法的原理都是实现了带有synchonize关键字的 *** 作方法
使用了一种叫读时共享, 写时复制的技术, 这可不是什么同步技术了
意思是每次修改集合L时时, 会复制生成一个与原来集合相同的集合L1, 然后对L1进行修改, 这时读还是读原来的集合L, 当修改完成时,将两个集合合并成修改之后的集合
这个使用的比较多
可以读读源码理解一下:
Set集合的解决方法类似的, HashSet也会产生线程不安全问题, 也有类似的解决方法,就是CopyOnWriteHashSet
用法不多解释, 瓢葫芦画瓢罢了
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)