
早期的编程实践中,直接使用新线程执行任务虽直观且易实现,但在高并发场景下却面临性能瓶颈。当系统需处理大量短暂并发任务时,频繁创建和销毁线程会导致巨大的开销,降低系统性能,甚至可能因资源过度消耗导致系统崩溃。为解决线程频繁创建和销毁的问题,我们需要高效复用线程的机制。
Java的线程池(Thread Pool)提供了这样的解决方案:预先创建并管理线程组,任务执行时从池中获取线程,任务完成后线程返回池中等待新任务。这种方式显著减少线程创建和销毁,大幅提升系统并发处理能力。
ThreadPoolExecutor类的概述Java中的ThreadPoolExecutor是线程池的核心实现,提供灵活的配置和管理方法。要深入理解其工作原理和使用,可从关键方法入手,逐步探索其实现逻辑。
ThreadPoolExecutor类的基本功能和作用在Java中,ThreadPoolExecutor是线程池框架的核心组件,它允许开发者以高度可配置和灵活的方式管理线程资源。其核心功能是为应用程序提供一个线程池,从而优化和控制线程的使用,特别是在处理大量并发任务时。
ThreadPoolExecutor管理一个线程池,当任务提交给线程池时,线程池会尝试复用已有的线程来执行任务,而不是为每个新任务都创建一个新线程。这大大减少了线程创建和销毁的开销。ThreadPoolExecutor允许你配置这个队列的大小和类型,以适应不同的应用场景。ThreadPoolExecutor允许你配置线程的生命周期,包括核心线程数、最大线程数、线程空闲时间等。当线程空闲超过指定时间后,多余的线程会被销毁以节省资源。ThreadPoolExecutor提供了几种内置的任务拒绝策略,同时也允许你自定义拒绝策略。ThreadPoolExecutor显著减少了线程创建和销毁的开销,从而提高了应用程序的性能。ThreadPoolExecutor允许你精细控制线程资源的使用,包括线程的数量、任务的排队策略等,从而更有效地管理系统的资源。ThreadPoolExecutor,开发者可以更加专注于业务逻辑的实现,而无需过多关注线程的管理和调度。ThreadPoolExecutor可以适应不同规模和需求的应用程序,提供了很好的扩展性。ThreadPoolExecutor主要构造函数及其参数
ThreadPoolExecutor 实现了 ExecutorService 接口, ExecutorService 扩展了 Executor 接口。
Executor:这是Java中执行已提交任务的对象的接口,提供了一种将任务与任务执行机制(通常是线程)解耦的方式。
ExecutorService:这是一个扩展了Executor接口的接口,它提供了更全面的生命周期管理(例如关闭、终止)和任务提交机制(例如execute, submit等)。ExecutorService通常用于控制和管理线程,它内部封装了一组线程,使得线程的使用更加简便和安全。
AbstractExecutorService:实际上,Java标准库中没有名为AbstractExecutorService的接口。可能您是想引用一个抽象类,但ExecutorService接口本身通常被具体类(如ThreadPoolExecutor)实现,而不是由抽象类来扩展。在标准库中,有一个AbstractExecutorService类的可能性很低,但如果有这样的类,它可能提供了一些ExecutorService接口的默认实现。
ThreadPoolExecutor:这是一个实现了ExecutorService接口的具体类,它提供了线程池的实现,允许用户配置核心线程数、最大线程数、线程空闲时间、任务队列等参数。ThreadPoolExecutor是线程池框架中最常用的实现之一,它高效地管理线程资源的复用,降低了系统的开销。
java.uitl.concurrent.ThreadPoolExecutor类是线程池中最核心的一个类,因此如果要透彻地了解Java中的线程池,必须先了解这个类。下面我们来看一下ThreadPoolExecutor类的具体实现源码。
public class ThreadPoolExecutor extends AbstractExecutorService {
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
BlockingQueue<Runnable> workQueue);
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory);
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler);
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);
...
}
从上面的代码可以得知,ThreadPoolExecutor继承了AbstractExecutorService类,并提供了四个构造器,事实上,通过观察每个构造器的源码具体实现,发现前面三个构造器都是调用的第四个构造器进行的初始化工作。
了解如何配置线程池。这包括设置核心线程数、最大线程数、队列容量等参数。这些参数的选择将直接影响线程池的性能和稳定性。通过合理地配置这些参数,我们可以在保证系统性能的同时,也避免了资源的过度消耗。

corePoolSize是线程池中的一个关键参数,它决定了线程池中的核心线程数量。
在创建线程池后,初始状态下线程池内部并不包含任何线程。线程池会等待任务的到来,并根据需要创建线程来执行任务。除非显式地调用 prestartAllCoreThreads() 或 prestartCoreThread() 方法,线程池才会预先创建核心线程。从这两个方法的名字就可以推断出,它们的目的是在未接收到任务之前就创建指定数量的线程。
在默认情况下,当第一个任务到达时,线程池会创建一个新线程来执行它。随着更多任务的到达,线程池中的线程数量会逐渐增加,直到达到 corePoolSize 所设定的数量。一旦线程池中的线程数量达到这个核心值,后续到达的任务将不再触发新线程的创建。
此时,如果还有新任务到来,线程池会将它们放入一个缓存队列中等待执行。这个队列通常是一个阻塞队列,用于存储待执行的任务。只有当队列满了,或者线程池中的线程数量低于 maximumPoolSize(最大线程池大小)时,线程池才会考虑创建额外的线程来执行任务。
注意:合理配置
corePoolSize,可以平衡线程创建和销毁的开销与任务执行的效率。如果corePoolSize设置得太小,可能会导致大量任务在队列中等待,从而增加任务的延迟;如果设置得太大,又可能浪费系统资源,因为不是所有线程都会同时处于忙碌状态。因此,在实际应用中,需要根据任务的特性和系统资源来合理设置这个参数。
线程池中的maximumPoolSize参数指的是线程池能够容纳的最大线程数量。当线程池中的线程数量达到这个值时,新的任务提交到线程池时,线程池将不会再创建新的线程来处理这些任务,而是根据线程池的其他策略(如队列策略)来决定如何处理这些新任务。
线程没有任务执行时最多保持多久时间会终止。
默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。
注意:如果调用了
allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0;
unit:参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:

一个阻塞队列,用来存储等待执行的任务,这个参数的选择也很重要,会对线程池的运行过程产生重大影响,一般来说,这里的阻塞队列有以下几种选择:

线程池中的阻塞队列(BlockingQueue)是线程池的一个重要组成部分,用于存储待执行的任务。当线程池中的线程数量达到corePoolSize时,新提交的任务会被放入这个队列中等待执行。阻塞队列的类型会影响线程池的行为和性能。以下是您提到的几种阻塞队列的作用和特性:
ArrayBlockingQueue(数组类型队列)
LinkedBlockingQueue(链表类型队列)
SynchronousQueue(同步单元素队列)
PriorityBlockingQueue(具有优先级的队列)
ArrayBlockingQueue和PriorityBlockingQueue使用较少,一般使用LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关。
线程工厂,主要用来创建线程的工厂实现类。
public interface ThreadFactory {
/**
* Constructs a new {@code Thread}. Implementations may also initialize
* priority, name, daemon status, {@code ThreadGroup}, etc.
*
* @param r a runnable to be executed by new thread instance
* @return constructed thread, or {@code null} if the request to
* create a thread is rejected
*/
Thread newThread(Runnable r);
}
表示当拒绝处理任务时的策略,有以下四种取值:
