当前位置: 首页 > 知识库问答 >
问题:

为什么Java中线程池的核心线程不能在初始阶段重用?

萧越泽
2023-03-14

我最近在查看ThreadPoolExecutor的源代码时遇到了一个问题:如果线程池表示重用现有线程以减少线程创建或销毁的开销,为什么不在初始阶段重用核心线程?也就是说,当当前线程数小于核心线程数时,首先检查是否有已完成任务的核心线程,如果有,请重用。为什么不呢?这是否违反了线程池设计原则,而不是在达到核心线程数之前创建新线程?

以下是对ThreadPoolExecutor中addWorker()方法的部分注释

  • @param firstTask新线程应首先运行的任务(如果没有,则为null)。当线程数少于corePoolSize时(在这种情况下,我们总是启动一个线程),或者当队列已满时(在这种情况下,我们必须绕过队列),将使用初始的第一个任务(在方法execute()中)创建工作线程以绕过队列。最初,空闲线程通常是通过预启动核心线程(prestartCoreThread)创建的,或者用来替换其他正在死亡的工作线程

共有1个答案

郑正阳
2023-03-14

这实际上已经被请求了:JDK-6452337。一位核心库开发人员指出:

我喜欢这个想法,但是ThreadPoolExector已经够复杂的了。

请记住,corePoolSizeThreadPoolExecitor的重要组成部分,它表示至少有多少工作人员始终处于活动/空闲状态。达到这个数字自然需要很短的时间。您根据自己的需要设置corePoolsize,预计工作负载将满足这个数字。

我的假设是,优化这个“热身阶段”——想当然地认为这实际上会提高效率——是不值得的。我无法为您量化此优化将带来的额外复杂性,我没有开发Java核心库,但我认为这不值得。

您可以这样想:“预热阶段”是恒定的,而线程池将运行一段未定义的时间。在理想情况下,初始阶段实际上不应该花费任何时间,在创建线程池时,工作负载应该在那里。因此,您正在考虑一种优化方法,该方法优化的内容不是预期的线程池状态。

无论如何,必须在某个时候创建线程工作线程。这种优化只会延迟创建。假设您的corePoolSize为10,那么至少需要创建10个线程。如果以后再做,这个开销不会改变。是的,资源也会稍后获取,但这里我首先要问的是线程池配置是否正确:corePoolSize是否正确,它是否满足当前的工作负载?

请注意,ThreadPoolExecutor具有setCorePoolSize(int)和allowCoreThreadTimeOut(boolean)等方法,允许您根据需要配置线程池

 类似资料:
  • 每个人我对使用线程池有一个误解。实际结果与该类的API描述不同。当我在线程池中使用时,它不重用线程,线程池等待构造函数中设置的KeepAliveTime,然后杀死这个线程并创建一个新线程。当我将KeepAliveTime设置为较小值时,比如1秒或更短,它会删除一个线程并重新创建它,但如果我设置一分钟,则不会创建新线程,因为不允许创建,队列已经满,所以所有任务都会被拒绝,但KeepAliveTime

  • 问题内容: 线程池有什么用?现实世界中有一个很好的例子吗? 问题答案: 线程池是最初创建的一组线程,它们等待作业并执行它们。这个想法是让线程始终存在,这样我们就不必每次都花时间来创建它们。当我们知道有大量工作要处理时,它们是合适的,即使可能有一段时间没有工作。 这是Wikipedia的一个不错的图表:

  • 主要内容:1 execute核心提交方法,2 addWorker尝试添加新线程,2.1 addWorkerFailed添加Worker失败处理,3 Worker线程包装类,3.1 runWorker执行工作基于JDK1.8详细介绍了ThreadPoolExecutor线程池的execute方法源码! 1 execute核心提交方法 public void execute(Runnable command) 传递一个Runnable任务对象,然后由线程池对它进行异步执行。没有办法检查Runnabl

  • 本文向大家介绍为什么要用线程池? 相关面试题,主要包含被问及为什么要用线程池? 时的应答技巧和注意事项,需要的朋友参考一下 池化技术相比大家已经屡见不鲜了,线程池、数据库连接池、Http 连接池等等都是对这个思想的应用。池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。** 线程池提供了一种限制和管理资源(包括执行一个任务)。 每个线程池还维护一些基本统计信息,例如已完成任务的数

  • 本文向大家介绍Java线程池框架核心代码解析,包括了Java线程池框架核心代码解析的使用技巧和注意事项,需要的朋友参考一下 前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和资源消耗都是很高的。线程池应运而生,成为我们管理线程的利器。Java 通过Executor接口,提供了一种标准的方法将任务的提交过程和执行过程解耦开来,并用Runnable表示任务。 下面,我们来分析一下

  • 线程池与任何ExecutorServices一样,我们定义了一个大小为3的newFixedPool。现在我有一个大约10000个可运行任务的队列。对于执行上述过程,我有这些疑问- > 要执行上述过程,执行者是否只允许来自任务queus的3个线程一次运行? 池将携带3个线程,这3个线程将只负责执行所有10000个任务。如果正确,单个线程如何运行不同的可运行任务,因为最终这些任务也是线程本身,并且在任