并行流修改的ArrayList的大小


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()。这会对你有所帮助。

相关内容

  • 没有找到相关文章

最新更新