在线程池的核心类ThreadPoolExecutor中,定义了几个线程池在运行过程中的核心状态,源码如下:
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
从源码中可以看出,线程池在运行过程中涉及的核心状态包括:RUNNING,SHUTDOWN,STOP,TIDYING,TERMINATED.具体含义解释如下:
由上图可知,线程池由RUNNING状态转换成TERMINATED状态需要经历过如下流程。
Executors类是JDK中提供的一个创建线程池的工具类,提供了多个创建线程池的方法,常用的创建线程池的方法如下:
当调用Executors.newCachedThreadPool方法创建线程池时,表示创建一个可缓存的线程池,如果线程池中的线程数超过了运行任务的需要,则可以灵活地回收空闲线程池。如果在向线程池提交新任务时,线程池中无空闲线程,则新创建线程来执行任务。
当调用Executors.newFixedThreadPool方法创建线程池时,表示创建一个固定长度的线程池,也就是线程池中的工作线程的数量是固定的,能够有效的控制线程池的最大并发数。当向线程池中提交任务时,如果线程池中有空闲线程,则执行任务。如果线程池中无空闲线程,则将任务放入阻塞队列中,待线程池中出现空线程池,再执行阻塞队列中的任务。
当调用Executors.newScheduledThreadPool方法创建线程池时,表示创建一个可以周期性执行任务的线程池,能够定时,周期性的执行任务。
当调用Executors.newSingleThreadExecutor方法创建线程池时,表示创建只有一个工作线程的线程池,即线程池中只有一个线程执行任务,能够保证提交到线程池中的所有任务按照先进先出的顺序,或者按照某个优先级的顺序来执行。当向线程池中提交任务时,如果线程池种无空闲线程,则会将任务保存到阻塞队列中。
当调用Executors.newSingleThreadScheduledExecutor方法创建线程池时,表示只创建一个工作线程的线程池,并且线程支持定时,周期性执行任务。
当调用Executors.newWorkStealingPool方法创建线程池时,表示创建一个具有并行级别的线程池。此方法时JDK1.8新增的方法,能够为线程池设置并行级别,具有比通过Executors类中的其他方法创建的线程池更高的并发度和性能。
查看ThreadPoolExecutor类的源码,其构造方法如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
通过源码可知,ThreadPoolExecutor类创建线程池时最终调用的构造方法如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
参数解析
从jdk1.8开始,java在Executors类中增加了work-stealing线程池的方法,源码如下:
public static ExecutorService newWorkStealingPool(int parallelism) {
return new ForkJoinPool
(parallelism,
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}
public static ExecutorService newWorkStealingPool() {
return new ForkJoinPool
(Runtime.getRuntime().availableProcessors(),
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}
从源码中可以看出,在调用Executors.newWorkStealingPool方法创建线程时,本质上调用的是ForkJoinPool类的构造方法,从代码结构上来看,ForkJoinPool类继承自AbstractExecutorService抽象类。ForkJoinPool类的构造方法如下:
public ForkJoinPool() {
this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()),
defaultForkJoinWorkerThreadFactory, null, false);
}
public ForkJoinPool(int parallelism) {
this(parallelism, defaultForkJoinWorkerThreadFactory, null, false);
}
public ForkJoinPool(int parallelism,
ForkJoinWorkerThreadFactory factory,
UncaughtExceptionHandler handler,
boolean asyncMode) {
this(checkParallelism(parallelism),
checkFactory(factory),
handler,
asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
"ForkJoinPool-" + nextPoolId() + "-worker-");
checkPermission();
}
private ForkJoinPool(int parallelism,
ForkJoinWorkerThreadFactory factory,
UncaughtExceptionHandler handler,
int mode,
String workerNamePrefix) {
this.workerNamePrefix = workerNamePrefix;
this.factory = factory;
this.ueh = handler;
this.config = (parallelism & SMASK) | mode;
long np = (long)(-parallelism); // offset ctl counts
this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
}
通过ForkJoinPool类的源码可知,在调用ForkJoinPool类的构造方法时,最终调用的是如下私有方法。
private ForkJoinPool(int parallelism,
ForkJoinWorkerThreadFactory factory,
UncaughtExceptionHandler handler,
int mode,
String workerNamePrefix) {
this.workerNamePrefix = workerNamePrefix;
this.factory = factory;
this.ueh = handler;
this.config = (parallelism & SMASK) | mode;
long np = (long)(-parallelism); // offset ctl counts
this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
}
参数说明
在Executors类中,提供了创建定时任务类线程池的方法,如下:
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1));
}
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1, threadFactory));
}
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
通过上述源码可以看出,在通过Executors类创建定时任务类的线程池时,本质上调用了ScheduledThreadPoolExecutor类的构造方法,在ScheduledThreadPoolExecutor类中,提供的构造方法如下:
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory);
}
public ScheduledThreadPoolExecutor(int corePoolSize,
RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), handler);
}
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory, handler);
}
而ScheduledThreadPoolExecutor类继承了ThreadPoolExecutor类,本质上ScheduledThreadPoolExecutor类的构造方法还是调用了ThreadPoolExecutor类的构造方法。只不过在ScheduledThreadPoolExecutor类的构造方法中,当调用了ThreadPoolExecutor类的构造方法时,传递的队列为DelayedWorkQueue。
ThreadPoolExecutor是java线程池中最核心的类之一,它能够保证线程按照正常的业务逻辑执行任务,并通过原子方式更新线程池每个阶段的状态。
ThreadPoolExecutor类中存在一个workers工作线程集合,用户可以向线程池中添加需要执行的任务,workers集合中的工作线程可以直接执行任务,或者从队列中获取任务后执行。
ThreadPoolExecutor类中提供了线程池从创建dao执行任务,再到消亡的整个流程方法。
线程池任务的核心流程可以简化为如下图所示:
由上图可以看出,当向线程池提交任务时,线程池执行任务的流程如下:
如果线程池中的workQueue阻塞队列已满,同时,线程池中的线程数已达到maximumPoolSize,并且没有空闲的线程,此时继续有任务提交到线程池,就需要采取某种策略来拒绝任务的执行。
在ThreadPoolExecutor类的execute()方法中,会有适当的时候调用reject(command)方法来执行拒绝策略。在ThreadPoolExecutor类中,reject(command)方法的实现如下:
final void reject(Runnable command) {
handler.rejectedExecution(command, this);
}
在reject(command)方法中调用了handler的rejectedExecution()方法。
public interface RejectedExecutionHandler {
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}
可以看到RejectedExecutionHandler是一个接口,其中定义了一个rejectedExecution()方法。在jdk中,默认有4个类实现了RejectedExectionHandler接口,分别为AbortPolicy,CallerRunsPolicy,DiscardOldestPolicy和DiscardPolicy。这4个类也正是线程池中默认提供的4中拒绝策略的实现类。
至于reject(command)方法具体汇之星哪个类的拒绝策略,是根据创建线程池时传递的参数决定的。如果没有传递拒绝策略的参数,则默认执行AbortPolicy类的拒绝策略;否则会执行传递的类的拒绝策略。
在创建线程池时,除了能够传递jdk默认提供的拒绝策略,还可以传递自定义的拒绝策略。如果想使用自定义的拒绝策略,则只需要实现RejectExecutionHandler接口,并重写rejectExecution(Runnable,ThreadPoolExecutor)方法。
调用shutdown()方法关闭线程池时,线程池不能接受新提交的任务,但是不会中断正在执行任务的线程,同时能够处理阻塞队列中已经保存的任务。待线程池中的任务全部执行完毕,线程池才会关闭。
在调用shutdownNow()方法关闭线程时,线程池不能接受新提交的任务,也不能继续处理阻塞队列中的任务,同时,还会中断正在执行的线程,使得正在执行的任务被中断,线程池立即关闭并抛出异常。