concurrency - 为什么parallelStream 使用的是ForkJoinPool,而不是普通的线程池?

标签 concurrency parallel-processing java-stream threadpool forkjoinpool

引用Java's Fork/Join vs ExecutorService - when to use which? ,一个传统的线程池通常用于处理很多独立的请求;和一个 ForkJoinPool用于处理连贯/递归任务,其中一个任务可能会产生另一个子任务并稍后加入。
那么,为什么 Java-8 的 parallelStream使用 ForkJoinPool默认情况下但不是传统的执行者?
在很多情况下,我们使用 forEach()stream() 之后或 parallelStream()然后提交一个功能接口(interface)作为参数。在我看来,这些任务是独立的,不是吗?

最佳答案

一件重要的事情是 ForkJoinPool也可以执行“正常”任务(例如 RunnableCallable ),因此它不仅仅用于递归创建的任务。
另一件(重要的)事情是 ForkJoinPool有多个队列,每个工作线程一个,用于任务,其中普通执行器(例如 ThreadPoolExecutor )只有一个。这对他们应该运行什么样的任务有很大影响。
普通 executor 必须执行的任务越小越多,将任务分配给 worker 的同步开销就越高。如果大部分任务都很小,worker 会经常访问内部任务队列,这会导致同步开销。
这里是ForkJoinPool它的多个队列闪耀着光芒。每个worker只从自己的队列中取任务,大部分时间不需要通过阻塞来同步,如果为空,可以从另一个worker那里偷任务,但是从队列的另一端,这也很少会导致同步开销,因为工作窃取应该很少见。
现在这与并行流有什么关系?流框架旨在易于使用。当您想轻松地将某些任务拆分为许多并发任务时,应该使用并行流,其中所有任务都相当小而简单。这是ForkJoinPool是合理的选择。它在大量较小的任务上提供了更好的性能,如果需要,它也可以处理更长的任务。

关于concurrency - 为什么parallelStream 使用的是ForkJoinPool,而不是普通的线程池?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61766068/

相关文章:

ruby-on-rails - 如何同时获取多个提要

javascript - Bluebird promise 库 : are . map 和 .filter 并行运行?

c - 将结构传递给 pthread_create 启动例程

java - Java 中的 Lambda 函数会跳过元素

Java - 如何将多个列表值连接到单个字符串中,并在每个值末尾添加分隔符

java - "delegation"如何帮助线程安全类?

Java Thread.join : what is the behaviour when calling join on multiple threads

javascript - 使用 mongoose 中间件删除依赖文档时的并发问题

matlab - 我如何知道 Matlab 中的 parfor 循环中还剩下多少次迭代?

java - 使用 Java Stream 从一组集合中收集所有对象