媒介
多线程编程中,为每个任务分派一个线程是不现实的,线程建设的开销和资源耗损都是很高的。线程池应运而生,成为我们打点线程的利器。Java 通过Executor接口,提供了一种尺度的要领将任务的提交进程和执行进程解耦开来,并用Runnable暗示任务。
下面,我们来阐明一下 Java 线程池框架的实现ThreadPoolExecutor。
下面的阐明基于JDK1.7
生命周期
ThreadPoolExecutor中,利用CAPACITY的高3位来暗示运行状态,别离是:
ThreadPoolExecutor顶用原子类来暗示状态位
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
线程池模子
焦点参数
线程池的最大容量:CAPACITY中的前三位用作符号位,也就是说事情线程的最大容量为(2^29)-1
四种模子
执行任务 execute
焦点逻辑:
1. 当前线程数量 < corePoolSize,直接开启新的焦点线程执行任务addWorker(command, true)
2. 当前线程数量 >= corePoolSize,且任务插手事情行列乐成
3. 开启普通线程执行任务addWorker(command, false),劳务派遣管理系统,开启失败就拒绝该任务
从上面的阐明可以总结出线程池运行的四个阶段:
拒绝计策
前面我们提到任务无法执行会被拒绝,RejectedExecutionHandler是处理惩罚被拒绝任务的接口。下面是四种拒绝计策。
线程池中的 Worker
Worker担任了AbstractQueuedSynchronizer和Runnable,前者给Worker提供锁的成果,后者执行事情线程的主要要领runWorker(Worker w)(从任务行列捞任务执行)。Worker 引用存在workers荟萃内里,用mainLock守护。
private final ReentrantLock mainLock = new ReentrantLock(); private final HashSet<Worker> workers = new HashSet<Worker>();
焦点函数 runWorker
下面是简化的逻辑,留意:每个事情线程的run都执行下面的函数
final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; while (task != null || (task = getTask()) != null) { w.lock(); beforeExecute(wt, task); task.run(); afterExecute(task, thrown); w.unlock(); } processWorkerExit(w, completedAbruptly); }
获取任务 getTask
线程池内部的任务行列是一个阻塞行列,详细实此刻结构时传入。
private final BlockingQueue<Runnable> workQueue;