Вы получите ConcurrentModificationException
- если вам повезет. Из документации об исключении наиболее релевантная часть:
Как правило, результаты итерации в этих обстоятельствах не определены. Некоторые реализации Iterator (включая реализации всех реализаций коллекций общего назначения, предоставляемых JRE) могут выбрасывать это исключение, если обнаруживается такое поведение. Итераторы, которые делают это, известны как итераторы с быстрым отказом, так как они быстро и чисто терпят неудачу, а не рискуют произвольным, недетерминированным поведением в неопределенное время в будущем.
Я попробовал этот пример кода:
List<Integer> myList = new ArrayList<>();
myList.add(1);
myList.add(2);
myList.add(3);
Thread threadA = new Thread(() -> {
try {
myList.add(4);
Thread.sleep(1000);
myList.add(5);
Thread.sleep(1000);
myList.add(6);
Thread.sleep(1000);
myList.add(7);
Thread.sleep(1000);
myList.add(8);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread threadB = new Thread(() -> {
myList.forEach(i -> {
try {
System.out.println(i);
Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
});
threadA.start();
threadB.start();
Что приводит к:
1
2
Exception in thread "Thread-1" java.util.ConcurrentModificationException
at java.util.ArrayList.forEach(ArrayList.java:1252)
at com.company.Main.lambda$main$2(Main.java:30)
at java.lang.Thread.run(Thread.java:748)
Отключение не-поточно-безопасного ArrayList
для синхронизированного Vector
результата:
1
2
3
4
Но вы не можете полагаться на это поведение. В документации совершенно ясно, что она не определена, и это может привести к изменению между различными реализациями или даже разными версиями. Не делай этого. Используйте потокобезопасные контейнеры, такие как Vector
и ConcurrentHashMap
, и используйте примитивы синхронизации вокруг них таким образом, чтобы иметь смысл для проблемы, которую вы пытаетесь решить.