当前位置: 首页 > 面试题库 >

并行流,收集器和线程安全

璩华辉
2023-03-14
问题内容

请参阅下面的简单示例,该示例计算列表中每个单词的出现次数:

Stream<String> words = Stream.of("a", "b", "a", "c");
Map<String, Integer> wordsCount = words.collect(toMap(s -> s, s -> 1,
                                                      (i, j) -> i + j));

最后wordsCount{a=2, b=1, c=1}

但是我的数据流很大,我想并行化作业,所以我写:

Map<String, Integer> wordsCount = words.parallel()
                                       .collect(toMap(s -> s, s -> 1,
                                                      (i, j) -> i + j));

但是我注意到这wordsCount很简单,HashMap所以我想知道是否需要显式请求并发映射以确保线程安全:

Map<String, Integer> wordsCount = words.parallel()
                                       .collect(toConcurrentMap(s -> s, s -> 1,
                                                                (i, j) -> i + j));

非并行收集器可以安全地与并行流一起使用吗?从并行流中收集时,我是否应该仅使用并发版本?


问题答案:

非并行收集器可以安全地与并行流一起使用吗?从并行流中收集时,我是否应该仅使用并发版本?

collect并行流的操作中使用非并行收集器是安全的。

在接口的规范中Collector,有六个要点的部分是:

对于非并发收集器,必须将结果提供者,累加器或组合器函数返回的所有结果串行地限制在线程中。这使收集可以并行发生,而收集器无需实现任何其他同步。简化实现必须管理输入已正确分区,分区被隔离处理以及仅在累加完成后才进行合并。

这意味着Collectors该类提供的各种实现可以与并行流一起使用,即使其中一些实现可能不是并发收集器也是如此。这也适用于您可能实现的任何您自己的非并行收集器。只要您的收集器不会干扰流源,无副作用,与订单无关等,它们就可以安全地与并行流一起使用。

我还建议阅读java.util.stream软件包文档中的Mutable
Reduction
一节。在本节的中间,有一个示例,该示例被声明为可并行化的,但是将结果收集到一个ArrayList不是线程安全的内。

这种工作方式是:以非并行收集器结尾的并行流可确保不同的线程始终在中间结果收集的不同实例上运行。这就是为什么收集器具有一个Supplier函数的功能,该函数用于创建与线程一样多的中间集合,因此每个线程可以累积到自己的线程中。当要合并中间结果时,它们将在线程之间安全地移交,并且在任何给定时间,只有一个线程将合并任何一对中间结果。



 类似资料:
  • 问题内容: 我想接受输入并对其应用并行流,然后我希望将输出作为列表。输入可以是任何列表或可以对其应用流的任何集合。 我在这里担心的是,如果我们要输出为map,我们可以从java中选择一个选项,例如 但是我看不到以线程安全的方式从并行流收集以提供列表作为输出的选项。我看到那里还有一个选择 通过这种方式,我们可以在collect方法中提供各种并发实现。但是我认为java.util.concurrent

  • 我想获取地图的值,找到min值,并为地图的每个条目构造一个新的CodesWitMinValue实例。我希望使用Java11个流,我可以在多行中使用多个流(一个用于min值,一个用于转换)来实现这一点。是否可以使用java 11流和收集器在单行中实现?谢谢。

  • 我知道这里之前有人问过这个问题:Kafka流并发? 但这对我来说很奇怪。根据文档(或者我可能遗漏了什么),每个分区都有一个任务,这意味着不同的处理器实例,每个任务由不同的线程执行。但是当我测试它的时候,我看到不同的线程可以得到不同的处理器实例。因此,如果你想在处理器中保持内存状态(老式的方式),你必须锁定? 线程ID:88 ID:c667e669-9023-494b-9345-236777e9df

  • 我有两个问题。其中一个会把话题弄得乱七八糟:) 1)我遇到了一个问题,即无法找到关于不同垃圾收集器在Hotspot中如何工作的完整信息。但我不是在谈论垃圾收集器工作的一般描述(我们在互联网上有很多这样的信息),我是在谈论具体的算法。我找到了这本白皮书(Java HotSpot虚拟机中的内存管理)http://www.oracle.com/technetwork/Java/javase/tech/m

  • 有没有办法把这两条流合并成一条?我使用第一个流在嵌套列表中进行过滤和查找,并使用第二个流根据流的结果创建地图。我想知道是否有一种方法可以用一条流来实现这一点。 像这样的

  • 欢迎阅读我的Java8并发教程的第一部分。这份指南将会以简单易懂的代码示例来教给你如何在Java8中进行并发编程。这是一系列教程中的第一部分。在接下来的15分钟,你将会学会如何通过线程,任务(tasks)和 exector services来并行执行代码。 并发在Java5中首次被引入并在后续的版本中不断得到增强。在这篇文章中介绍的大部分概念同样适用于以前的Java版本。不过我的代码示例聚焦于Ja