1. 前言
从Java 1.5 开始,并发包里面提供了Executors类,这个类提供了几种线程池的实现。下面对ExecutorService以及几种线程池进行说明。
2.ExecutorService
ExecutorService 接口继承自 Executor 接口,它提供了更丰富的实现多线程的方法。
ExecutorService的生命周期有三种状态:
- 运行 创建之后便进入运行状态
- 关闭 当调用shutdown()方法之后就进入关闭状态
- 终止 调用shutdown(),当已有的任务执行完毕之后就进入终止状态
shutdown方法会”平滑的”关闭,也就是说,会不在接受新的任务,而已接受的任务(不管是执行中还是等待中),都会继续。
3. Executors
- newFixedThreadPool,创建一个固定数目的线程池。
- newCachedThreadPool,创建一个可缓冲线程的线程池,也就是先查看有没有以前创建的可用的线程,如果有就重用,没有就创建新的,线程空闲等待的时间是60s,如果60s之内没有重用,就会被回收。
- newScheduledThreadPool,创建调度性线程池,可以延迟执行或者周期性执行
- newSingleThreadExecutor,创建一个单一工作线程的线程池,
上面的四种线程池是从Java 1.5 开始提供的。在Java 1.8 当中,提供了一种新的线程池。
- newWorkStealingPool,实现了工作窃取算法的线程池,这个,我们现在暂且不说。
而Java 1.5 提供的四种线程池,newFixedThreadPool,newCachedThreadPool,都是由ThreadPoolExecutor来实现的。newScheduledThreadPool是由ThreadPoolExecutor的子类ScheduledThreadPoolExecutor来实现的。newSingleThreadExecutor是由DelegatedScheduledExecutorService(代理类来实现的)。
4. ThreadPoolExecutor
其涉及到核心变量如下:
- corePoolSize 核心线程数
- maximumPoolSize 最大线程数
- keepAliveTime 当线程池中的线程数超过corePoolSize的空闲线程最大存活时间
- TimeUnit keepAliveTime时间单位
- workQueue 阻塞任务队列
- threadFactory 新建线程工厂
- RejectedExecutionHandler 当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理
其生命周期和ExecutorService稍有不同。如下
关于ThreadPoolExecutor的实现原理,可以看一下几篇文章。
5. ScheduledThreadPoolExecutor
ScheduledThreadPoolExecutor实现了ScheduledExecutorService接口,实现了调度的功能。
- schedule 延迟一段时间执行
- scheduleAtFixedRate 连续周期行执行
- scheduleWithFixedDelay 以固定的延迟执行
关于ScheduledThreadPoolExecutor更多的资料可以看下面文章:
- 深度解析Java8 – ScheduledThreadPoolExecutor源码解析
- Android Java 线程池 ScheduledThreadPoolExecutor源码篇
- 自行google或者查看源码以及阅读源码注释
6. DelegatedExecutorService
这个就是ExecutorService的一个代理类,可以自行查阅源码。
7. 排队策略
说道线程池,肯定是存在排队策略的。下面简单介绍下几种排队策略。
- 直接提交 缓冲队列采用 SynchronousQueue,将任务直接交给线程处理而不保存他们 newCachedThreadPool
- 无界队列 典型的便是采用预定义容量的 LinkedBlockingQueue,所有的corePoolSize线程都在工作中,新任务将提交到缓存队列中。 newSingleThreadExecutor
- 有界队列 当使用有限的 maximumPoolSizes 时,一般缓冲队列使用 ArrayBlockingQueue,并制定队列的最大长度