了解了解Java线程池执行原理线程池执行原理
那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?在Java中可以通过线程池来达到这样的效果。
下面我们来详细了解一下吧
前言前言
上一篇已经对线程池的创建进行了分析,了解线程池既有预设的模板,也提供多种参数支撑灵活的定制。
本文将会围绕线程池的生命周期,分析线程池执行任务的过程。
线程池状态线程池状态
首先认识两个贯穿线程池代码的参数:
runState:线程池运行状态
workerCount:工作线程的数量
线程池用一个32位的int来同时保存runState和workerCount,其中高3位是runState,其余29位是workerCount。代码中会反复使用runStateOf和workerCountOf来获取runState和
workerCount。
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// 线程池状态
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;
// ctl操作
private static int runStateOf(int c) { return c & ~CAPACITY; }
private static int workerCountOf(int c) { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
RUNNING:可接收新任务,可执行等待队列里的任务
SHUTDOWN:不可接收新任务,可执行等待队列里的任务
STOP:不可接收新任务,不可执行等待队列里的任务,并且尝试终止所有在运行任务
TIDYING:所有任务已经终止,执行terminated()
TERMINATED:terminated()执行完成
线程池状态默认从RUNNING开始流转,到状态TERMINATED结束,中间不需要经过每一种状态,但不能让状态回退。下面是状态变化可能的路径和变化条件:
Worker的创建的创建
线程池是由Worker类负责执行任务,Worker继承了AbstractQueuedSynchronizer,引出了Java并发框架的核心AQS。
AbstractQueuedSynchronizer,简称AQS,是Java并发包里一系列同步工具的基础实现,原理是根据状态位来控制线程的入队阻塞、出队唤醒来处理同步。
AQS不会在这里展开讨论,只需要知道Worker包装了Thread,由它去执行任务。
调用execute将会根据线程池的情况创建Worker,可以归纳出下图四种情况: