O primeiro é nosso ArrayList:
Desta vez, explicamos a insegurança das coleções, em primeiro lugar, todos nós conhecemos o ArrayList!
Em primeiro lugar, expandimos alguns pontos de conhecimento. A camada inferior de ArrayList é uma matriz do tipo Object. A capacidade inicial é 10 (antes de jdk7, depois de jdk8 ser uma referência nula, ela se tornará 10 após adicionar, semelhante ao mecanismo de carregamento lento), e seu método de expansão Cada expansão é metade da anterior. Por exemplo, 10 será expandido para 15 e 15 será expandido para 22. O método usado para expansão é o método copyof de Arrays. OK, então entre no tópico.
Olhe para este código primeiro:
List<String> list=new ArrayList<>();
Então, usamos expressões Lambda para gerar vários threads
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();
}
Uma exceção será relatada posteriormente:
java.util.ConcurrentModificationException
Causa da
exceção de modificação simultânea : Competição de simultaneidade multi-threaded para recursos uniformes e nenhum bloqueio. Então, quais soluções temos ? ?
método um:
List<String> list = new Vector<>();
Coleção de vetores, a camada inferior adiciona synchronized (relocking) ao método add. Há apenas um thread ao mesmo tempo, o que é ineficiente, então é por isso que a coleção é ineficiente e segura.
Método dois:
Collections.synchronizedList(new ArrayList<>());
Este é um método estático de Connections, passando em um ArrayList.
Método três:
List<String> list = new CopyOnWriteArrayList<>();
A classe deste pacote JUC implementa a interface List.
Camada inferior: array Object [] volátil
tem um bloqueio ReentrantLock em seu método 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();
}
}
**
Em seguida, olhamos para a coleção Set:
Os mesmos pontos de conhecimento estendido, a estrutura de dados subjacente de HashSet é HashMap (new HashMap () no construtor de código-fonte) e seu método add realmente retorna map.put (e, PRESENT ) == null; PRESENT é na verdade um objeto sempre ativo , Portanto, são realmente as chaves do HashMap.
As mesmas etapas:
Set<String> set=new HashSet<>();
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();
}
O mesmo é um erro:
java.util.ConcurrentModificationException
Solução:
Método 1:
Set<String> set=Collections.synchronizedSet(new HashSet<>());
Método dois:
Set<String> set=new CopyOnWriteArraySet();
Também é uma classe em JUC e seu construtor é, na verdade, new CopyOnWriteArrayList ();
Então é o nosso Mapa:
Conhecimento estendido: a camada inferior do HashMap (não ordenado e sem repetição) é matriz + lista vinculada (unidirecional) + árvore vermelha e preta, o HashMap armazena o nó e o nó armazena o valor-chave. A capacidade inicial do HashMap é 16 e o fator de carga é 0,75 ( Expanda a capacidade quando atingir 16 * 0,75), a capacidade inicial e o fator de carga podem ser alterados através do construtor, e a capacidade original será duplicada a cada vez.
Map<String, String> map = new HashMap<>();
for (int i = 0; i < 30; i++) {
new Thread(() -> {
map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 8));
System.out.println(map);
}, String.valueOf(i)).start();
}
O mesmo erro será relatado: solução
java.util.ConcurrentModificationException
:
Map<String, String> map = new ConcurrentHashMap();
Sob o pacote JUC.
Desta vez, o acervo do JUC explicou que esse momento não é seguro. Espero que possa te ajudar. Se você tiver sugestões melhores, deixe seu recado!