参考this接受的答案中的第三点,是否存在使用blocking
进行长时间运行计算无论是CPU还是IO-毫无意义或不好的情况绑定,即在Future
内执行?
答案 0 :(得分:5)
From my practice,blocking
+ ForkJoinPool
如果要处理大量消息并且每个消息需要长时间阻止(这也意味着它),可能导致线程的连续和无法控制的创建在此期间保留一些记忆。无论ForkJoinPool
如何,MaxThreadCount
都会创建新线程以补偿“可管理的被阻止”线程。向VisualVm中的数百个线程问好。它几乎会杀死背压,因为池中的任务总是有一个位置(如果你的背压基于ThreadPoolExecutor
的策略)。新线程分配和垃圾收集都会破坏性能。
所以:
blocking{}
(无锁)期间实际使用你的CPU是没有意义的,因为它只会增加线程数而不是系统中真实核心数。 P.S。 blocking
隐藏在Await.result
内,因此并不总是很明显。在我们的项目中,有人在一些基础工作者角色中做了这样的Await
。
答案 1 :(得分:4)
这取决于您ExecutionContext
正在执行的Future
。
<强>毫无意义:强>
如果ExecutionContext
不是BlockContext
,那么使用blocking
将毫无意义。也就是说,它将使用DefaultBlockContext,它只是执行代码而无需任何特殊处理。它可能不会增加那么多开销,但仍然毫无意义。
<强>为:强>
当线程池即将耗尽时,Scala的ExecutionContext.Implicits.global
将在ForkJoinPool
中生成新线程。也就是说,如果知道将通过blocking
发生。如果您正在生成批次线程,这可能会很糟糕。如果您在很短的时间内排队等待大量工作,global
上下文将很快扩展,直到陷入僵局。 @ dk14的答案更深入地解释了这一点,但要点是它可能是一个性能杀手,因为托管阻塞实际上很快就会变得无法管理。
blocking
的主要目的是避免线程池中的死锁,因此它与性能在切向相关,因为达到死锁会比产生更多线程更糟糕。但是,它绝对不是一个神奇的性能增强器。
我已在this answer中详细了解了blocking
。