【问题标题】:Java8 stream().map().reduce() is really map reduceJava8 stream().map().reduce() 是真正的map reduce
【发布时间】:2017-06-28 07:03:19
【问题描述】:

我在某处使用 stream().map().reduce() 看到了这段代码。

这个 map() 函数真的可以并行工作吗?如果是,那么它可以为 map() 函数启动的最大线程数是多少?

如果我在以下特定用例中使用 parallelStream() 而不是仅使用 stream() 会怎样。

谁能给我一个不使用parallelStream()的好例子

下面的代码只是从 tCode 中提取 tName 并返回逗号分隔的字符串。

String ts = atList.stream().map(tcode -> {
    return CacheUtil.getTCache().getTInfo(tCode).getTName();
}).reduce((tName1, tName2) -> {
    return tName1 + ", " + tName2;
}).get();

【问题讨论】:

  • 好吧。您是否对此主题进行过任何研究或尝试过您的 coden-p?

标签: java java-8


【解决方案1】:

这个stream().map().reduce()不是并行的,因此单个线程作用于流。

您必须添加 parallel 或在其他情况下添加 parallelStream(取决于 API,但它是同一件事)。 默认情况下使用并行,您将获得可用处理器的数量 - 1;但是ForkJoinPool#commonPool中也使用了主线程;因此通常会有 2、4、8 个线程等。要检查您将获得多少线程,请使用:

Runtime.getRuntime().availableProcessors()

您可以使用自定义池并获取任意数量的线程,如here 所示。

还要注意,整个管道是并行运行的,而不是只是map 操作。

没有关于何时使用和何时不使用并行流的黄金法则,最好的方法是衡量。但是有明显的选择,比如 10 个元素的流 - 这方式太少了,无法从并行化中获得任何真正的好处。

【讨论】:

  • “您可以使用自定义池并获取任意数量的线程...” - 但如果计算受 CPU 限制,则创建的线程数将超过可用内核数不会加快速度。
  • @StephenC 是的...我认为链接问题中也提到了这一点
【解决方案2】:

所有并行流都使用通用的 fork-join 线程池,如果您提交一个长时间运行的任务,您实际上会阻塞池中的所有线程。因此,您会阻止所有其他使用并行流的任务。

只有两种选择可以确保这种事情永远不会发生。首先是保证所有提交到common fork-join pool的任务不会被卡住,并且会在合理的时间内完成。但说起来容易做起来难,尤其是在复杂的应用程序中。另一种选择是不使用并行流并等到 Oracle 允许我们指定用于并行流的线程池。

用例 假设您有一个集合(列表),它在应用程序开始时加载了值,并且在以后的任何时候都不会向其中添加新值。在上述场景中,您可以毫无顾虑地使用并行流。

不用担心流是高效且安全的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    • 2010-09-28
    • 1970-01-01
    • 2013-05-25
    相关资源
    最近更新 更多