【发布时间】:2018-10-12 14:45:57
【问题描述】:
当HashMap 的一个实例被多个Threads 读写时,我一直在尝试重现(并解决)ConcurrentModificationException。
免责声明:我知道HashMap 不是线程安全的。
在以下代码中:
import java.util.*;
public class MyClass {
public static void main(String args[]) throws Exception {
java.util.Map<String, Integer> oops = new java.util.HashMap<>();
oops.put("1", 1);
oops.put("2", 2);
oops.put("3", 3);
Runnable read = () -> {
System.out.println("Entered read thread");
/*
* ConcurrentModificationException possibly occurs
*
for (int i = 0; i < 100; i++) {
List<Integer> numbers = new ArrayList<>();
numbers.addAll(oops.values());
System.out.println("Size " + numbers.size());
}
*/
for (int i = 0; i < 100; i++) {
List<Integer> numbers = new ArrayList<>();
numbers.addAll(oops.values()
.stream()
.collect(java.util.stream.Collectors.toList()));
System.out.println("Size " + numbers.size());
}
};
Runnable write = () -> {
System.out.println("Entered write thread");
for (int i = 0; i < 100; i++) {
System.out.println("Put " + i);
oops.put(Integer.toString(i), i);
}
};
Thread writeThread = new Thread(write, "write-thread");
Thread readThread = new Thread(read, "read-thread");
readThread.start();
writeThread.start();
readThread.join();
writeThread.join();
}
}
基本上,我创建了两个线程:一个不断将元素放入HashMap,另一个在HashMap.values() 上迭代。
在read 线程中,如果我使用numbers.addAll(oops.values()),ConcurrentModificationException 会随机出现。虽然这些行是按预期随机打印的。
但如果我切换到numbers.addAll(oops.values().stream()..,我不会收到任何错误。然而,我观察到一个奇怪的现象。 read 线程的所有行都打印在 write 线程打印的行之后。
我的问题是,Collection.stream() 是否有某种内部同步?
更新:
使用JDoodle https://www.jdoodle.com/a/IYy,好像在JDK9和JDK10上,我会按预期得到ConcurrentModificationException。
谢谢!
【问题讨论】:
标签: java multithreading java-stream