Executor框架
Executor类:在java.util.concurrent类中,是JDK并发包的核心类。
ThreadPoolExecutor: 线程池。
Excutors: 线程池工厂,通过Executor可以创建一个特定功能的线程池。
一)、Executor框架的类的关系
Executor, ExecutorService, AbstractExcutorService, ThreadPoolExecutor,Executors
Eecutor类:
接口,只有一个execute()方法:
public interface Executor {
void execute(Runnable command);
}
ExecutorService extends Executor类:
接口,ExecutorService extends Executor,主要方法如下:
//关闭线程池
void shutdown();
boolean isShutdown();
List<Runnable> shutdownNow();
boolean isTerminated();
<T> Future<T> submit(Callable<T> task);
//提交线程任务,并返回执行结果
Future<?> submit(Runnable task);
AbstractExecutorService类:
abstract class AbstractExecutorService implements ExecutorService,主要实现submit()方法。
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
//内部还是调用了execute()
execute(ftask);
return ftask;
}
ThreadPoolExecutor类:
class ThreadPoolExecutor extends AbstractExecutorService
二)、线程池的状态:
参考:https://blog.csdn.net/nobody_1/article/details/98335594
运行(RUNNING): 线程池接收新任务,并处理队列中的任务。
关机(SHUTDOWN): 线程池不接受新的任务,但接收队列的任务,调用
shutdown()后线程的状态。
停止(STOP): 线程池不接受新的任务,也不处理队列中的任务,并中断执行中
的任务,调用shutdownNow()线程的状态。
清理(tidying): 线程池所有任务已经终止,workCount(当前线程个数)为0,过渡
到清理状态的线程将运行terminated()的子方法 。
终止(terminated): terminate()方法结束后线程的状态。
//线程池的容量11111111111111111111111111111: 29个1
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
//运行状态,-2^29,10000000000000000000000000000,1个1,29个0
private static final int RUNNING = -1 << COUNT_BITS; // 关机状态 0
private static final int SHUTDOWN = 0 << COUNT_BITS;
// 停止 2^29
private static final int STOP = 1 << COUNT_BITS;
// 清理状态 2 * 2^29
private static final int TIDYING = 2 << COUNT_BITS;
// 终止状态 3 * 2^29
private static final int TERMINATED = 3 << COUNT_BITS;
注:使用线程的高三位代表线程的状态,使用低29位代表工作线程的个数。
三)、获取池状态
private static int runStateOf(int c){
//获得高3位
return c & ~ CAPACITY;
}
四)、获得工作线程数
private static int workerCountOf(int c){
return c & Capacity;
}
五)、使用AtomicInteger变量来表示线程池状态和工作线程数量
//刚开始初始化时,线程的状态默认为RUNNING, 工作线程个数为0
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0))
//rs:运行状态(runState), wc:工作线程数 (workCount)
private static int ctlOf(int rs, int wc) {
return rs | wc;
}
使用ctl可以获取线程状态和工作线程数
int c = ctl.get();
runStateOf(c): 获取运行状态
workerCountOf(c): 获取工作线程数
六)、线程池对象:ThreadPoolExecutor
1)、主要属性:
//线程池的锁
private final ReentrantLock mainLock = new ReentrantLock();
//线程池中重用线程对象
private final HashSet<Worker> workers = new HashSet<Worker>();
//最大线程个数
private int largestPoolSize;
//当线程超过最大核心线程数时的阻塞队列
private final BlockingQueue<Runnable> workQueue;
//实时监控线程池的状态和工作线程的个数
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;
//线程池的运行状态
// 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;
2)、构造方法:
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.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
3)、参数信息:
corePoolSize: 指定了线程池中的线程数量
maximumPoolSize: 指定线程池中的最大线程数量
KeepAliveTime: 超过corePoolSize后增加的线程的空闲时间,超过这个时间线程
未使用,则销毁该线程。
unit: KeepAliveTime的单位
workQueue: 任务队列,被提交但尚未被执行的任务
threadFactory: 线程工厂,一般用于创建线程。
handle: 拒绝策略,当任务太多,来不及处理,如何拒绝任务。
七)、workeQueue:等待队列
1).SynchronousQueue:直接提交的队列
特点: 没有容量,每一个插入操作都要等待一个相应的删除操作。
作用:应用于new CacheThreadPool线程池的workerQueue队列,不保存任务,
总 是将任务提交给线程执行,如果没有空闲的进程,则尝试创建新的线
程,如果进程的数量达到最大值,则执行拒绝策略。
注: 一直创建新的线程,直至线程数到达maximumPoolSize,执行拒绝策略。
2).ArrayBlockingQueue: 有界队列
特点:使用构造函数,指定队列的最大容量
public ArrayBlockingQueue(int capacity){
}
作用:当有新的任务要执行时,如果线程池的实际线程数小于coreSize,则会优先
创建新的线程,若大于corePoolSize,则会将新任务加入等待队列,若等
待队已满,在总线程数不大于maximumPoolSize的前提下创建线程,当总
线程 数超过maxmmumPoolSize时执行拒绝策略。
** 注:**当线程数小于coreSize时,创建新的线程,大于coreSize时,将任务加入
等待 队列,直至等待队列加满,在总线程数不超过maximumPoolSize的前
提下创建线程,否则,执行拒绝策略。
3).LinkedBlockingQueue: 无界队列
特点:除非资源耗尽,否则无界队列不存在任务入队失败的情况。
作用:系统有任务时,若总的线程数小于corePoolSize则创建新的线程,否则,
则将线程添加至等待队列中,无界队列保持快速增长,直至耗尽系统内
存。
** 注:** 当线程数小于corePoolSize时,创建新的线程,大于corePoolSize时,将
任务加入等待队列中,直至耗尽系统内存,线程的个数一直维护在
corePoolSize 。
4).PriorityBlockingQueue: 优先任务队列
特点:控制任务的执行先后顺序,是一个特殊的无界队列
作用:根据任务自身的优先级先后执行
八)、handler,JDK内置的四种拒绝策略
1). AbortPolicy: 直接抛出异常,阻滞系统工作
2).CallerRunsPolicy: 在调用者线程中运行当前被丢弃任务
3).DiscardOledstPolicy: 丢弃最老的一个请求,即即将被执行的一个任务,并尝试
再次提交当前任务。
4).DiscardPolicy: 丢弃无法处理的任务,不予任何处理。
注:若要自定义拒绝策略,实现RejecteExecutionHandler接口,实现
rejectedExecution方法。
九)、execute()方法
步骤:
1)、参数传递,得到一个任务对象
2)、判断
//Runnable command 当前要执行的线程任务
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
//获取定前线程池的状态
int c = ctl.get();
//判断当前主线程数量是否超过corePoolSize,如果不超过,则新建一个线程对象
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//将任务添加到等待队列中,若队列未满,添加。已满,执行拒绝策略
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//队列已满,执行拒绝策略回调
else if (!addWorker(command, false))
reject(command);
}
//线程池中添加新的线程,并执行线程任务
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
//获取运行状态
int rs = runStateOf(c);
// Check if queue empty only if necessary.
//如若当前处于关闭、清理、终止,任务队列不为空时返回false,因为,队列不为空,说明线程个数达到核心线程的个数,不能创建新的线程值,返回false
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
//获取当前的主线程数
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//增加线程池的大小
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
//重新创建一个线程
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
//线程池中添加新线程
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
//执行线程任务
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
七)、Executors:线程池工厂
继承ThreadPoolExecutor,可以取得一个特定功能的线程池
构造方法:
注:所有的线程池的构造,其内部最终都是调用了ThreadPoolExecutor的构造方法
1)、newFixThreadPool(int nThread): 创建一个固定大小的线程池
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
2)、newSingleThreadExecutor(): 返回一个只有一个线程的线程池
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
- 、new CacheThreadPool(): 返回一个可以根据实际情况调整线程数量的线程池
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
4)、new SingleThreadSchaduleExecutor(): 返回一个ScheduleExecutor对象,
retry: 标记循环位置,在continur和break后面加retry表示循环直接跳出到retry标
记处。
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1));
}