1.实现原理
下图所示为线程池的实现原理:调⽤⽅不断地向线程池中提交任务;线程池中有⼀组线程,不断地从队列中取任
务,这是⼀个典型的⽣产者
—
消费者模型。
![](https://i-blog.csdnimg.cn/blog_migrate/0f0d136bcd767e77ecfb88351c14f478.png)
要实现这样⼀个线程池,有⼏个问题需要考虑:
1.
队列设置多⻓?如果是⽆界的,调⽤⽅不断地往队列中放任务,可能导致内存耗尽。如果是有界的,当队列
满了之后,调⽤⽅如何处理?
2.
线程池中的线程个数是固定的,还是动态变化的?
3.
每次提交新任务,是放⼊队列?还是开新线程?
4.
当没有任务的时候,线程是睡眠⼀⼩段时间?还是进⼊阻塞?如果进⼊阻塞,如何唤醒?
针对问题
4
,有
3
种做法:
1.
不使⽤阻塞队列,只使⽤⼀般的线程安全的队列,也⽆阻塞
/
唤醒机制。当队列为空时,线程池中的线程只能
睡眠⼀会⼉,然后醒来去看队列中有没有新任务到来,如此不断轮询。
2.
不使⽤阻塞队列,但在队列外部、线程池内部实现了阻塞
/
唤醒机制。
3.
使⽤阻塞队列。
很显然,做法
3
最完善,既避免了线程池内部⾃⼰实现阻塞
/
唤醒机制的麻烦,也避免了做法
1
的睡眠
/
轮询带来的
资源消耗和延迟。正因为如此,接下来要讲的
ThreadPoolExector/ScheduledThreadPoolExecutor
都是基于阻塞队列
来实现的,⽽不是⼀般的队列,⾄此,各式各样的阻塞队列就要派上⽤场了。
2.线程池的类继承体系
![](https://i-blog.csdnimg.cn/blog_migrate/16d663ffb1de7e3dd699b7b3ad6117b3.png)
在这⾥,有两个核⼼的类:
ThreadPoolExector
和
ScheduledThreadPoolExecutor
,后者不仅可以执⾏某个
任务,还可以周期性地执⾏任务。
向线程池中提交的每个任务,都必须实现
Runnable
接⼝,通过最上⾯的
Executor
接⼝中的
execute(Runnable command)
向线程池提交任务。
然后,在
ExecutorService
中,定义了线程池的关闭接⼝
shutdown()
,还定义了可以有返回值的任务,也就
是
Callable
,后⾯会详细介绍。
3.
ThreadPoolExecutor
基于线程池的实现原理,下⾯看⼀下
ThreadPoolExector
的核⼼数据结构。
public class ThreadPoolExecutor extends AbstractExecutorService {
//...
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// 存放任务的阻塞队列
private final BlockingQueue<Runnable> workQueue;
// 对线程池内部各种变量进⾏互斥访问控制
private final ReentrantLock mainLock = new ReentrantLock();
// 线程集合
private final HashSet<Worker> workers = new HashSet<Worker>();
//...
}
每⼀个线程是⼀个
Worker
对象。
Worker
是
ThreadPoolExector
的内部类,核⼼数据结构如下:
private final class Worker extends AbstractQueuedSynchronizer implements Runnable {
// ...
final Thread thread; // Worker封装的线程
Runnable firstTask; // Worker接收到的第1个任务
volatile long completedTasks; // Worker执⾏完毕的任务个数
// ...
}
由定义会发现,
Worker
继承于
AQS
,也就是说
Worker
本身就是⼀把锁。这把锁有什么⽤处呢?⽤于线程池的关
闭、线程执⾏任务的过程中。
4.核⼼配置参数解释
ThreadPoolExecutor在其构造⽅法中提供了⼏个核⼼配置参数,来配置不同策略的线程池
![](https://i-blog.csdnimg.cn/blog_migrate/18ca9b1e64a9a9aba41f540a0f9ec7e9.png)
上⾯的各个参数,解释如下:
1. corePoolSize
:在线程池中始终维护的线程个数。
2. maxPoolSize
:在
corePooSize
已满、队列也满的情况下,扩充线程⾄此值。
3. keepAliveTime/TimeUnit
:
maxPoolSize
中的空闲线程,销毁所需要的时间,总线程数收缩回
corePoolSize
。