关于这接受的答案中的第三点,是否有任何情况是没有意义的或坏的,在长期运行的计算中使用blocking,无论是CPU还是IO绑定的,在Future中执行。
发布于 2015-04-16 02:04:13
这取决于您的ExecutionContext正在执行的Future。
无意义:
如果ExecutionContext不是BlockContext,那么使用blocking就没有意义了。也就是说,它将使用DefaultBlockContext,它只是执行代码,而不需要任何特殊处理。它可能不会增加那么多开销,但还是毫无意义。
Bad:
Scala的ExecutionContext.Implicits.global是为了在线程池即将耗尽时在ForkJoinPool中生成新线程。也就是说,如果它知道这将通过blocking发生的话。这可能是不好的,如果你产卵了很多线程。如果您在短时间内排队等待大量工作,global上下文将很高兴地扩展,直到陷入僵局。@ be 14的回答更深入地解释了这一点,但最重要的是它可以成为性能杀手,因为管理阻塞实际上会很快变得难以管理。
blocking的主要目的是避免线程池中的死锁,因此它与性能密切相关,因为达到死锁比产生更多的线程更糟糕。然而,它绝对不是一个神奇的性能增强剂。
我写了更多关于blocking的文章,特别是在这个答案中。
发布于 2015-04-16 01:49:34
从我的实践中、blocking + ForkJoinPool可能会导致线程的连续和不可控制的创建,如果您需要处理大量消息,并且每条消息都需要长时间阻塞(这也意味着它在此过程中保存了一些内存)。ForkJoinPool创建新线程来补偿“可管理阻塞”线程,而不管MaxThreadCount;向VisualVm中的数百个线程问好。而且它几乎可以消除反压力,因为池的队列中总是有一个任务的位置(如果您的背压是基于ThreadPoolExecutor的策略的话),新线程分配和垃圾收集都会影响性能。
所以:
blocking{}期间实际使用您的CPU (没有锁),这是没有意义的,因为它只会增加线程的数量,而不是系统中真正核心的数量。P.S. blocking隐藏在Await.result内部,所以并不总是很明显。在我们的项目中,有人在某个潜在的工作者角色中做了这样的Await。
https://stackoverflow.com/questions/29663410
复制相似问题