stream和parallelStream [英] stream and parallelStream

查看:435
本文介绍了stream和parallelStream的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的测试代码:

List<Integer> list = new ArrayList<>(1000000);

for(int i=0;i<1000000;i++){
    list.add(i);
}

List<String> values = new ArrayList<>(1000000);

list.stream().forEach(
    i->values.add(new Date().toString())
);

System.out.println(values.size()); 

运行此项,我得到了正确的输出:1000000。

Running this, I got a correct output: 1000000.

但是,如果我将 stream()更改为 parallelStream(),则为:

However, if I change the stream() to parallelStream(), as this:

 list.parallelStream().forEach(
    i->values.add(new Date().toString())
 );

我得到一个随机输出,例如:920821。

I got a random output, e.g.: 920821.

出了什么问题?

推荐答案

ArrayList 未同步。未定义尝试同时向其添加元素。来自 forEach


对于并行流管道,此操作不保证尊重流的遭遇顺序,因为这样做会牺牲并行性的好处。 对于任何给定元素,可以在任何时间以及库选择的任何线程中执行操作

在你的第二个例子中,你最终得到多个线程,调用 add on数组列表同时和 ArrayList 文档说:

In your second example, you end up with multiple threads calling add on the array list at the same time and ArrayList documentation says:


注意这个实现不同步。如果多个线程同时访问ArrayList实例,并且至少有一个线程在结构上修改了列表,则必须在外部进行同步。

Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally.



错误的解决方案



如果您将 ArrayList 的使用更改为 Vector ,你们'将获得正确的结果,因为此列表实现是同步的。它的Javadoc说:

The wrong solution

If you change the use of an ArrayList to a Vector, you'll get the correct result, because this list implementation is synchronized. Its Javadoc says:


与新的集合实现不同, Vector 是同步的。

然而,不要使用它!此外,由于显式同步,它可能最终变慢。

However, do not use it! Furthermore, it might end up being slower because of the explicit synchronization.

显然是为了避免Stream API提供可变减少范例,使用 collect 方法。以下

It is explicitly to avoid this situation that the Stream API provides the mutable reduction paradigm, with the use of the collect method. The following

List<String> values = list.stream().map(i -> "foo").collect(Collectors.toList());

将始终提供正确的结果,无论是否并行运行。 Stream管道内部处理并发性,保证使用非并发收集器是安全的在并行流的收集操作中 Collectors.toList() 是一个内置的收集器,将Stream的元素累积到列表中。

will always provide the correct result, whether run in parallel or not. The Stream pipeline internally handles the concurrency and guarantees that it is safe to use a non-concurrent collector in a collect operation of a parallel stream. Collectors.toList() is a built-in collector accumulating the elements of a Stream into a list.

这篇关于stream和parallelStream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆