Ho cercato di dimostrare che c'è un bug nell'applicazione creando un semplice test unitario che sta mettendo i valori sulla mappa. Mi aspettavo ConcurrentModificationException
, ma tutto quello che ho ottenuto è stato appendere i thread nell'esecutore e non vedo dove sia esattamente il problema.Perché il codice si blocca con HashMap.put() da più thread?
La prova è qui:
@Test
public void testHashMap() throws Exception {
final Random rnd = new Random();
final Map<String, Object> map = new HashMap<>();
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
final int counter=i;
executor.execute(new Runnable() {
@Override
public void run() {
try{
for (int j = 0; j<1000; j++){
map.put(String.valueOf(rnd.nextLong()), new Object());
//map.put("A", new Object());
}
System.out.println("Thread "+counter+" finished");
}catch(Exception e){
System.out.println("Thread "+counter+" failed with exception: ");
e.printStackTrace();
}
}
});
}
executor.shutdown();
int i = 0;
while (!executor.isTerminated()) {
i++;
Thread.sleep(1000);
System.out.println("Waited "+i+" seconds");
}
}
So che non dovrei farlo, ma io non capisco perché non ricevo un'eccezione e perché i fili semplicemente appendere là? Quando faccio un semplice put
sulla mappa (il codice commentato), poi passa bene.
Ecco l'esempio di output:
Thread 0 finished
Thread 1 finished
Thread 4 finished
Thread 2 finished
Thread 5 finished
Thread 7 finished
Thread 9 finished
Thread 10 finished
Thread 13 finished
Thread 6 finished
Thread 14 finished
Thread 8 finished
Thread 12 finished
Thread 16 finished
Thread 19 finished
Thread 20 finished
Thread 21 finished
Thread 26 finished
Thread 25 finished
Thread 24 finished
Thread 28 finished
Thread 3 finished
Thread 31 finished
Thread 30 finished
Thread 32 finished
Thread 34 finished
Thread 35 finished
Thread 36 finished
Thread 37 finished
Thread 38 finished
Thread 39 finished
Thread 22 finished
Thread 27 finished
Thread 42 finished
Thread 43 finished
Thread 41 finished
Thread 45 finished
Thread 44 finished
Thread 47 finished
Thread 48 finished
Thread 49 finished
Waited 1 seconds
Waited 2 seconds
Waited 3 seconds
Waited 4 seconds
Waited 5 seconds
...indefinitely
Non è possibile utilizzare un 'HashMap' senza sincronizzazione esterna. Dovresti passare a usare 'ConcurrentHashMap'. – Gray
So che non dovrei usarlo e perché, ma non capisco perché sto osservando il comportamento del test. – NeplatnyUdaj
Il multithreading inserisce in un 'HashMap' può causare loop infiniti se le catene di elenchi collegate vengono messe in uno stato corrotto dove diventano accidentalmente liste concatenate. –