List<Integer> data = new ArrayList<>();
IntStream.range(0,100).parallel().forEach(data::add);
System.out.println(data.size());
为什么上面的代码不总是打印100?当打印结果为94时,这些未计数的数字会发生什么情况?我知道我可以使用forEachOrdered(), CopyOnWriteArrayList或Collections.synchronizedList()。但是在上面的例子中缺少6个元素到底会发生什么呢?是不是每个线程都有自己的数组列表副本然后把它们组合起来?
因为ArrayList
不是线程安全的
当两个线程试图同时增加该计数器时,其中一个线程会覆盖另一个线程的结果。
试着用threadsafe collection来做,你会没事的。
ArrayList<E>
不是同步/线程安全的,这就是为什么。
可以使用同步列表,如:
List<Integer> data = Collections.synchronizedList(new ArrayList<>());
IntStream.range(0,100).parallel().forEach(data::add);
System.out.println(data.size());
或forEachOrdered,如:
List<Integer> data = new ArrayList<>();
IntStream.range(0,100).parallel().forEachOrdered(data::add);
System.out.println(data.size());
正如它的文档所说:
操作可以在库选择的任何线程中执行。
例如,您可以使用synchronizedCollection()。这会对你有所帮助。