任何人都可以指出正确的方向,因为我无法理解问题。
我正在执行以下方法。
private static void reduce_parallelStream() {
List<String> vals = Arrays.asList("a", "b");
List<String> join = vals.parallelStream().reduce(new ArrayList<String>(),
(List<String> l, String v) -> {
l.add(v);
return l;
}, (a, b) -> {
a.addAll(b);
return a;
}
);
System.out.println(join);
}
它打印
[null,a,null,a]
我不明白为什么将两个空值放在结果列表中。我希望答案是
[a,b]
因为它是并行流,所以第一个要减少的参数
新的ArrayList()
每个输入值a和b可能会被调用两次。
然后,累加器函数可能会被调用两次,因为它是parallelStream,并在每次调用中传递每个输入“a和b”以及种子值提供的列表。因此,将a添加到列表1,将b添加到列表2(反之亦然)。之后,组合器将合并两个列表,但不会发生。
有趣的是,如果我在累加器中放置一个print语句以打印输入值,则输出会更改。所以下面
private static void reduce_parallelStream() {
List<String> vals = Arrays.asList("a", "b");
List<String> join = vals.parallelStream().reduce(new ArrayList<String>(),
(List<String> l, String v) -> {
System.out.printf("l is %s", l);
l.add(v);
System.out.printf("l is %s", l);
return l;
}, (a, b) -> {
a.addAll(b);
return a;
}
);
System.out.println(join);
}
结果输出
l是[] l是[b] l是[b,a] l是[b,a] [b,a,b,a]
谁能解释一下。
最佳答案
使用Collections.synchronizedList()
时,应该使用parallelStream()
。因为ArrayList
并非线程安全的,并且您在并发访问它时会遇到意外行为,就像使用parallelStream()
一样。
我已经修改了您的代码,现在可以正常使用了:
private static void reduce_parallelStream() {
List<String> vals = Arrays.asList("a", "b");
// Use Synchronized List when with parallelStream()
List<String> join = vals.parallelStream().reduce(Collections.synchronizedList(new ArrayList<>()),
(l, v) -> {
l.add(v);
return l;
}, (a, b) -> a // don't use addAll() here to multiplicate the output like [a, b, a, b]
);
System.out.println(join);
}
输出:
有时您会得到以下输出:
[a, b]
有时这个:
[b, a]
原因是它是一个
parallelStream()
,因此您不确定执行顺序。