我最近在查看threadpoolexecutor的源代码时遇到了一个问题:如果线程池表示重用现有线程以减少线程创建或销毁的开销,那么为什么不在初始阶段重用核心线程呢?也就是说,当当前线程数小于核心线程数时,首先检查是否有已完成任务的核心线程,如果有,则重用。为什么不?这不是在达到核心线程数之前创建新线程,而是违反了线程池设计原则吗?
以下是对threadpoolexecutor中addworker()方法的部分注解
@param firsttask新线程应该首先运行的任务(如果没有,则为null)。worker是用一个初始的第一个任务(在execute()方法中)创建的,当线程少于corepoolsize时(在这种情况下,我们总是启动一个线程),或者当队列已满时(在这种情况下,我们必须绕过队列)。最初空闲线程通常是通过prestartcorethread创建的,或者用来替换其他正在消亡的工作线程。
1条答案
按热度按时间fkaflof61#
这实际上已经被请求了:jdk-6452337。一位核心库开发人员指出:
我喜欢这个想法,但threadpoolexecutor已经够复杂了。
请记住
corePoolSize
是一个重要的组成部分ThreadPoolExecutor
并且说至少有多少工人总是活跃/空闲的。达到这个数字自然需要很短的时间。你准备好了吗corePoolSize
根据您的需要,预计工作量将达到这个数字。我的假设是,优化这个“热身阶段”——想当然地认为这实际上会提高效率——是不值得的。我无法量化这种优化会带来什么额外的复杂性,我没有开发java核心库,但我认为这不值得。
您可以这样想:“预热阶段”是恒定的,而线程池将运行一段未定义的时间。在理想情况下,初始阶段实际上不需要花费任何时间,工作负载应该在创建线程池时出现。因此,您正在考虑一种优化方法,它优化的内容不是预期的线程池状态。
无论如何,线程工作线程必须在某个时刻创建。这种优化只会延迟创建。想象你有一个
corePoolSize
所以至少要创建10个线程。如果你以后再做,这个开销不会改变。是的,资源也会在稍后获取,但这里我首先要问的是线程池配置是否正确:是吗corePoolSize
正确,它是否满足当前的工作量?注意
ThreadPoolExecutor
有这样的方法setCorePoolSize(int)
以及allowCoreThreadTimeOut(boolean)
以及更多允许您根据需要配置线程池的功能。