目录
0 框架类图
常用的Executors类是工具类,静态工厂方法(简单工厂模式),实际生产ThreadPoolExecutor。
ThreadPoolExecutor是核心实现类,下面来详细介绍
1. Executors工具类
API如下,常用几种种静态工厂方法newFixedThreadPool固定大小、newSingleThreadExecutor单线程、newCachedThreadPool、newScheduledThreadPool固定时延(定时任务),实际生产出来的都是ThreadPoolExecutor
ThreadPoolExecutor 构造参数 |
newFixedThreadPool(n) | newSingleThreadExecutor() | newCachedThreadPool() | newScheduledThreadPool(n) |
---|---|---|---|---|
corePoolSize | n(方法参数) | 1 | 0 | n |
maximumPoolSize | n | 1 | Integer.MAX_VALUE | Integer.MAX_VALUE |
keepAliveTime | 0 | 0 | 60 | 0 |
unit | MILLISECONDS毫秒 | MILLISECONDS毫秒 | SECONDS秒 | MILLISECONDS毫秒 |
workQueue | LinkedBlockingQueue | LinkedBlockingQueue | SynchronousQueue | DelayedWorkQueue |
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
...
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());
}
2 ThreadPoolExecutor
2.1 API常用方法
2.1.1 构造方法
有4个构造方法,最常用第一个,带5个参数,参数接受稍后详解,
剩余的就是多指明线程工厂和拒绝策略,线程工厂用与创建线程,而拒绝策略就是在提交任务数 > maxPoolSize+queueSize时拒绝线程。
第一个构造方法如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue);
ThreadPoolExecutor 是Executor的基本实现,构造参数如下,通过这些参数可以控制其大小等
参数 | 含义 | 图解 |
---|---|---|
corePoolSize | 线程池基本大小 | |
maximumPoolSize | 线程池最大大小 | |
keepAliveTime | 线程存活时间, 空间时间**>keepAliveTime 标记为可回收 |
|
unit | 时间单位, 枚举可设置为秒、毫秒等 |
|
workQueue | 工作队列类型 |
2.1.2 核心方法execute(Runnable r)
提交任务到线程池
2.1.3 addWorker创建工作线程
前置会判断当前的线程数量,此处省略了,当符合size条件符合(如上图展示),就会
new Worker实例(会使用线程工厂threadFactory创建一个以当前worker为Runnable参数的新线程),
然后一些状态判断,并加入到线程池ThreadPoolExecutor的workers集合,
最后启动线程start,调度后就能执行这个Worker的run方法。具体请见下面Worker章节~
2.2 组件解析
主要包含Worker、ThreadFactory、BlockingQueue
2.2.1 worker
就是工作线程,实现了Runnable,并持有Runnable
构造方法
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
run方法
主要是在while循环体中一直从任务队列中获取Runnable任务,直接调用其run方法,所以并不是提交多少次就会生产多少线程去执行任务的,工作线程是复用的,工作线程的run方法中循环调用任务的run方法而已。(命令模式)
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // 允许中断
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) { // 首次任务||从队列获取任务workQueue.take();
w.lock();
// 如果线程池被置为stoping,中断线程 否则保证不中断
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);// 空实现
try {
task.run(); // 执行任务!!!
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);// 空实现
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly); // 空闲且非core则销毁worker
}
}
2.2.2 ThreadFactory
ThreadFactory是个接口,顾名思义就是用于生产线程的工厂,(简单工厂模式),我们通常不指定这个参数,所以会选用默认的实现。
默认实现DefaultThreadFactory是Executors的静态内部类,主要生产线程的方法非常简单,如下
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(),0);
if (t.isDaemon())
t.setDaemon(false); //非守护线程
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY); //普通优先级
return t;
}
2.2.3 BlockingQueue
通常的生产者/消费者模型会选择使用BlockingQueue,主要特性就是在空时取会阻塞,满时offer会阻塞,家族如下,