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

Concurrency 为什么parallelStream使用ForkJoinPool,而不是普通的线程池?,concurrency,parallel-processing,java-stream,threadpool,forkjoinpool,Concurrency,Parallel Processing,Java Stream,Threadpool,Forkjoinpool,参考,传统的线程池通常用于处理许多独立的请求;而ForkJoinPool用于处理一致性/递归任务,其中一个任务可能会生成另一个子任务并在稍后加入 那么,为什么Java-8的parallelStream默认使用ForkJoinPool,而不是传统的执行器呢 在许多情况下,我们在stream()或parallelStream()之后使用forEach(),然后提交函数接口作为参数。在我看来,这些任务是独立的,不是吗?一个重要的事情是,ForkJoinPool也可以执行“正常”任务(例如,可运行的,可

参考,传统的线程池通常用于处理许多独立的请求;而
ForkJoinPool
用于处理一致性/递归任务,其中一个任务可能会生成另一个子任务并在稍后加入

那么,为什么Java-8的
parallelStream
默认使用
ForkJoinPool
,而不是传统的执行器呢


在许多情况下,我们在
stream()
parallelStream()
之后使用
forEach()
,然后提交函数接口作为参数。在我看来,这些任务是独立的,不是吗?

一个重要的事情是,
ForkJoinPool
也可以执行“正常”任务(例如,
可运行的
可调用的
),因此它不仅仅用于递归创建的任务

另一件(重要的)事情是,
ForkJoinPool
对于任务有多个队列,每个工作线程一个队列,而普通执行器(例如
ThreadPoolExecutor
)只有一个队列。这对他们应该运行什么样的任务有很大影响

正常执行者必须执行的任务越小、越多,将任务分配给工作人员的同步开销就越高。如果大多数任务都很小,工作人员将经常访问内部任务队列,这会导致同步开销

这里是
ForkJoinPool
因其多个队列而闪耀的地方。每个worker只从自己的队列中获取任务,这在大多数情况下不需要通过阻塞来同步,如果队列为空,它可以从另一个worker窃取任务,但从队列的另一端窃取任务,这也很少导致同步开销,因为偷取工作被认为是非常罕见的

那么这与并行流有什么关系呢?streams框架设计为易于使用。当您希望在许多并发任务中轻松地分割某些内容时,应该使用并行流,因为所有任务都非常小和简单。这里的
ForkJoinPool
是合理的选择。它在大量较小的任务上提供了更好的性能,如果必须的话,它还可以处理更长的任务。

forEach
是一个终端操作。即使您“在许多情况下”使用它,它也肯定不会推动软件的设计决策,因为软件仍然必须支持所有这些决策。除此之外,我认为前缀是最不常用的终端操作,常常导致开发人员编写“按另一个名称循环”代码。