ArrayListに起因する一連の問題
EDITORIAL:CopyOnWriteArrayListと、CopyOnWriteArraySet、のConcurrentHashMap、しっかりjava.util.ConcurrentModificationExceptionがを忘れないようにしてください
- 新しいArrayListを()新しい何か根本的な?配列
- 基礎となるのはどのような種類?オブジェクトが保持することができ、結果としてふりをすることができlist.add考えます
- 初期値にJava8例はどのくらいですか?空のアドオン10の後にスタート
- デポジット25の要素が行うことができますか?はい、10「15を拡大するための方法を根本的な拡大は、半分の元の値を広めます
- あなたがソースコードを読んでいない、どのように移動するには?Arrays.copyOf()
- 数を拡大するための第2膨張?22ハッシュマップの拡張は「32 16の倍元の値であります
- 7.ArrayListスレッドセーフまたは安全ではありませんか?安全でありません
- たとえば、危険なコードをスレッド?
- ベクターは、なぜそれをArrayListを持っている、スレッドセーフですか?同時実行性と一貫性がなく、多くの同時実行、ロックテーブル、一つだけのスレッド操作の前に、オッズで自分自身であります
- 解決するためにどのように危険なスレッド?
- なぜセキュリティの書き込みをコピー?
package com.magic.juc0117;
/**
* @Description
* @Author Chelsea
* @Date 2020/1/17 17:18
*/
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.function.Consumer;
/**
* 1.故障现象
* java.util.ConcurrentModificationException
* 2.导致原因
* 多线程并发争抢同一个资源类并且没有加锁
* 3.解决方法
* ① List<String> list = new Vector<>();//源码加锁synchronized(重锁)
* 根据效率和安全性选择,电商ArrayList不多
* 不许用vector,请用②解决
* ②List<String> list = Collections.synchronizedList(new ArrayList<>());
* 如果②也不让用
* ③List<String> list = new CopyOnWriteArrayList();//写时复制
*
* 4.优化建议(同样的错误不能犯2次)
*/
/**
* 一个常问的题目:Collection 和 Collections有什么区别?
* Collection 接口 Collections集合接口的工具类
*/
public class NotSafeDemo03 {
public static void main(String[] args) {
listNotSafe();
//同理HashSet、HashMap也是线程不安全的,JUC也提供了对应的安全的类
// Set<String> set = new HashSet<>();
Set<String> set = new CopyOnWriteArraySet<>();
for (int i = 0; i < 30; i++) {
new Thread(() -> {
set.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(set);
},String.valueOf(i)).start();
}
//HashMap ConcurrentHashMap
}
public static void listNotSafe(){
// List<String> list = new ArrayList();
// list.add("a");
// list.add("a");
// list.add("a");
// list.forEach(System.out::println); 这样不会不安全只有一个线程,下面for循环会异常ConcurrentModificationException
// 换成下面三种方式时异常解决
// List<String> list = new Vector<>();//源码加锁synchronized
// List<String> list = Collections.synchronizedList(new ArrayList<>());
List<String> list = new CopyOnWriteArrayList();//写时复制
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.HashSet底层数据结构 HashMap 也不安全
* 选择CopyOnWriteArraySet
*/
/**
* HashMap
* ConcurrentHashMap
*/
}
回答の質問は非常に先頭に、なぜセキュリティの書き込みをコピー?
以下、ソースコードがロックを知ることができるソースCopyOnWriteArrayListとクラスadd()メソッドであり、同時ロックリエントラントと効率が大幅に向上します。
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();
}
}
仕上げ学びJUC。