Gen*_*zer 5 java multithreading java-stream
我一直在尝试重现(并解决)ConcurrentModificationException当一个实例HashMap被多个Threads 读取和写入时.
免责声明:我知道这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();
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,我创建了两个线程:一个继续将元素放入a 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预期的结果.
谢谢!
你所看到的一切绝对是偶然的;请记住,内部System.out.println执行 a synchronzied; 因此,可能会以某种方式使结果看起来按顺序出现。
我没有太深入地研究你的代码 - 因为分析 Why HashMap,这不是线程安全的,是 miss 行为很可能是徒劳的;如您所知,它被记录为非线程安全的。
关于这一点ConcurrentModificationException,文档明确表示它将尽力抛出该问题;所以要么是java-8在这一点上较弱,要么这又是偶然的。
| 归档时间: |
|
| 查看次数: |
100 次 |
| 最近记录: |