在Fork-Join线程池中,一个长时间运行的任务是否会阻塞所有线程?

5
我一直在学习Java 8的并行流,通过谷歌搜索我找到了这篇文章。但是我无法理解文章中的这句话:

...所有的并行流都使用共同的fork-join线程池,如果您提交了一个长时间运行的任务,您将有效地阻塞池中的所有线程

我不明白一个长时间运行的任务如何会阻塞池中的所有其他线程。
2个回答

9
在这个语句中,“提交一个长时间运行的任务”意味着“使用并行流执行长时间运行的任务”。并行流处理的“意图”是将工作拆分并分配给公共线程池的所有工作线程。
该线程池配置了一定数量的线程以利用所有 CPU 核心,如果所有核心都很忙碌,则已达到目标。
如果这些线程被阻塞在等待 I/O 操作完成时,就会出现问题。然后,CPU 核心就无法利用,这不仅可能降低其他并行流的性能,即使在相同操作中,最大并发 I/O 操作数与 CPU 核心数完全不同,也可能导致问题。
结论是,Stream API 不适用于并行 I/O 操作。

我知道这是一个旧帖子,但我也有同样的问题。如果我们运行并行流,我们不能在第一个并行流完成之前启动第二个并行流(即使一些线程来自分叉加入池处于空闲状态)? - alfer
1
@alfer,这个问题是关于被阻塞的线程,而不是空闲的线程。如果在你的情况下,线程是空闲的,但没有用于另一个并行操作,那么听起来你有一个新的问题。 - Holger

2

提交一个任务不能使用公共池中的所有线程。公共池大小为核心数-1(主线程减1)。

我认为在文章中,他的意思是在API中无法将IO密集型任务和CPU密集型任务分别分配到不同的池中。
例如,在8核机器上,如果您将8个CPU密集型任务提交到池中,然后再提交8个IO密集型任务,则IO任务必须等待CPU密集型任务完成(反之亦然)。如果您可以将它们提交到不同的池中,则所有16个操作都可以并发运行,因为IO操作对CPU的成本不高。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接