线程池核心参数,线程池工作模型
线程池有 7 个参数,需要重点关注corePoolSize、maximumPoolSize、workQueue、handler 这四个。

ThreadPoolExecutor 是 Java 并发包 java.util.concurrent 中提供的一个灵活的线程池实现。它允许你通过多个参数来定制线程池的行为,以满足不同的应用需求。以下是 ThreadPoolExecutor 的主要构造器参数及其意义:
构造器参数
1 | public ThreadPoolExecutor(int corePoolSize, |
corePoolSize(核心线程数):线程池中的核心线程数,即使这些线程处于空闲状态,也不会被销毁。除非设置了
allowCoreThreadTimeOut。maximumPoolSize(最大线程数):线程池允许的最大线程数。当队列满了,并且已创建的线程数小于
maximumPoolSize,则线程池会再创建新线程来处理任务。keepAliveTime(线程空闲时间):当线程数大于核心线程数时,这是多余空闲线程在终止前等待新任务的最长时间。
unit(时间单位):
keepAliveTime参数的时间单位,可以是TimeUnit枚举中的任何一个值,如TimeUnit.SECONDS、TimeUnit.MILLISECONDS等。workQueue(任务队列):用于保存等待执行的任务的阻塞队列。当提交的任务数超过
corePoolSize,这些任务会被保存在队列中,直到线程变得可用。threadFactory(线程工厂):用于创建新线程。这通常用于设置线程名、优先级、是否为守护线程等属性,或者使用自定义的
ThreadFactory来创建具有特定UncaughtExceptionHandler的线程。handler(拒绝策略):当
workQueue满了,并且已创建的线程数达到maximumPoolSize时,线程池无法处理新提交的任务,此时将调用此处理器来处理这种情况。Java 提供了几种预定义的拒绝策略实现,如AbortPolicy(直接抛出RejectedExecutionException)、CallerRunsPolicy(调用者运行任务)、DiscardOldestPolicy(丢弃队列中最旧的任务)、DiscardPolicy(不处理,直接丢弃任务)。
执行逻辑
ThreadPoolExecutor 的执行逻辑大致如下:
当提交一个新任务时,线程池首先会尝试使用当前空闲的核心线程来执行任务。
如果当前核心线程数已经达到
corePoolSize,新任务会被添加到workQueue中等待执行。如果
workQueue已满,并且当前线程数还没有达到maximumPoolSize,线程池会创建一个新线程来处理任务。如果
workQueue已满,且线程数已经达到maximumPoolSize,线程池会根据所设置的RejectedExecutionHandler来处理新提交的任务。当一个线程完成任务时,它会在等待新的任务。如果线程池中的线程数超过了
corePoolSize,并且这些线程在keepAliveTime内没有接到新的任务,它们会被终止。这有助于减少资源消耗。
通过调整这些参数,你可以根据应用程序的具体需求来优化线程池的性能。例如,对于 CPU 密集型任务,你可能希望将 corePoolSize 和 maximumPoolSize 设置为相同的值,以充分利用系统的计算能力。对于 I/O 密集型任务,你可能希望设置一个较大的 maximumPoolSize,以便在等待 I/O 操作完成时,可以处理更多的任务。
当 ThreadPoolExecutor 的 corePoolSize 设置为 0 时,其执行逻辑会有所不同。以下是 corePoolSize 为 0 时的执行逻辑概述:
提交新任务:当向线程池提交一个新任务时,由于
corePoolSize为 0,线程池不会立即创建核心线程来处理这个任务。判断任务队列:接下来,线程池会检查任务队列(
workQueue)是否已满。如果队列未满,新任务将被放入队列中等待执行。创建新线程:如果任务队列已满,并且线程池中的当前线程数还没有达到
maximumPoolSize,线程池会创建一个新线程来处理任务。尽管corePoolSize为 0,但线程池仍然会根据需要创建新线程,直到达到maximumPoolSize的限制。拒绝策略:如果任务队列已满,且线程数已达到
maximumPoolSize,那么线程池会根据设置的拒绝策略(RejectedExecutionHandler)来处理新提交的任务。可能的处理方式包括直接抛出异常、调用者运行任务、丢弃最旧的任务或不处理直接丢弃任务。
需要注意的是,尽管 corePoolSize 为 0,但线程池仍然可以创建新线程来处理任务,只要任务队列已满且当前线程数未达到 maximumPoolSize。这与 corePoolSize 大于 0 的情况不同,在 corePoolSize 大于 0 时,线程池会优先使用核心线程来处理任务。
此外,由于 corePoolSize 为 0,线程池中没有固定的核心线程,所有线程都是根据需要动态创建的。这意味着在没有任务提交时,线程池中的线程可能会被销毁(如果它们超过了 maximumPoolSize 并且在 keepAliveTime 内没有接到新任务),从而节省系统资源。
总的来说,当 corePoolSize 为 0 时,线程池的执行逻辑更加灵活,可以根据任务的提交情况和队列的状态动态地创建和销毁线程。这种配置通常适用于那些任务提交频率不高,或者需要快速响应的任务场景。