【问题标题】:Is this IntStream partioning implementation really not thread safe?这个 IntStream 分区实现真的不是线程安全的吗?
【发布时间】:2020-07-29 18:41:38
【问题描述】:

这个answer 提供了一个分割 IntStream 的实现:

IntStream intStream = IntStream.iterate(0, i -> i + 1).limit(1000000);

Predicate<Integer> p = x -> r.nextBoolean();
Map<Boolean, List<Integer>> groups = intStream.collect(() -> {
    Map<Boolean, List<Integer>> map = new HashMap<>();
    map.put(false, new ArrayList<>());
    map.put(true, new ArrayList<>());
    return map;
}, (map, x) -> {
    boolean partition = p.test(x);
    List<Integer> list = map.get(partition);
    list.add(x);
}, (map1, map2) -> {
    map1.get(false).addAll(map2.get(false));
    map1.get(true).addAll(map2.get(true));
});

System.out.println(groups.get(false).size());
System.out.println(groups.get(true).size());

但它的编辑提到这个实现不是线程安全的。然而,据我所知,收集器为并行流中的每个线程创建一个单独的HashMap&lt;List&lt;Integer&gt;&gt;。所以每个地图都被限制在一个线程中。分区功能也仅限于单个线程。合并函数合并来自多个线程的结果,但据我所知,流框架确保合并以线程安全的方式完成。所以我的问题是:这个解决方案真的不是线程安全的吗?

顺便说一句:无论如何,答案提供了一个更优雅的解决方案(Stream&lt;Integer&gt; stream = intStream.boxed(); 等),但我仍然想知道。

PS:我想将此问题作为评论添加到原始帖子中,但我什至没有添加 cmets 的声誉...:|

【问题讨论】:

  • 链接的答案已更正。

标签: java multithreading concurrency java-stream


【解决方案1】:

好吧,Random 是线程安全的,但不应以这种方式使用,因为它在争用时性能很差,但 ArrayList 不是线程安全的。使用并行流,您将从多个线程调用 list.add(x)

【讨论】:

  • 感谢您的回复。我的观点是,并行流中的每个工作线程都会创建自己的带有数组列表的映射。 (这就是你提供供应商而不是地图本身的原因。)所以所有这些地图和列表都被限制在它们自己的工作线程中,这使得这个解决方案线程安全。
【解决方案2】:

根据 Oracles 文档

与 reduce(int, IntBinaryOperator) 一样,collect 操作可以并行化,无需额外同步。

https://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html#collect-java.util.function.Supplier-java.util.function.ObjIntConsumer-java.util.function.BiConsumer-

看来你的直觉是正确的,这是线程安全的。

【讨论】:

  • 当然它们并不意味着整个块是同步的,那会杀死并发性。他们可能意味着从流的角度来看它是线程安全的。 list.add(x) 调用不是线程安全的。如果能同时调用就有问题了!
  • @ewramner 它不是同步的,但是每个工作线程都有自己的ArrayList,或者,在这个特定的例子中,它有自己的两个ArrayLists。请参阅Mutable Reduction section of the documentation。所以程序逻辑确保list.add(x) 永远不会在同一个列表上同时调用。另见the difference between concurrent and non-concurrent collectors
猜你喜欢
  • 1970-01-01
  • 2021-05-12
  • 2010-12-10
  • 2023-03-06
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多