线程池参数
public ThreadpoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler){}
1. corePoolSize:线程池核心线程大小
2. maximumPoolSize: 线程池最大线程数量
3. keepAliveTime: 空闲线程存活时间
4. unit:空闲线程存活时间单位
5. workQueue: 工作队列 (1.ArrayBlocking 2.LinkedBlockingQueue 3.SynchronizedQueue 4.PriorityBlockingQueue)
6. ThreadFactory:线程工厂
7. Handler 拒绝策略(工作队列任务已达到最大限制,并且线程池中数量已最大,有新任务进来怎么办?)
- CallerRunsPolicy:在调用者线程中直接执行被拒绝任务的run方法,除非线程池已经shutdown,则直接抛弃任务;
- AbortPolicy:直接丢弃任务,并抛出RejectedExecutionException异常
- Discardpolicy:直接丢弃,什么都不做
- DiscardOldestPolicy:抛弃进入队列,最早的那个任务,然后尝试把这次拒绝的任务放入队列
Java通过Executors提供四种线程池
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个可定期或者延时执行任务的定长线程池,支持定时及周期性任务执行。
newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
核心队列
ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列
LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列(常用)
PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列
DelayQueue: 一个使用优先级队列实现的无界阻塞队列
SynchronousQueue: 一个不存储元素的阻塞队列(常用)
LinkedTransferQueue: 一个由链表结构组成的无界阻塞队列
LinkedBlockingDeque: 一个由链表结构组成的双向阻塞队列
线程池的状态
1. 线程池有运行,关闭,停止,结束四种状态,结束后就会释放所有资源
2. 平缓关闭线程池使用shutdown()
3. 立即关闭线程池使用shutdownNow(),同时得到来执行的任务列表
4. 检测线程池是否处于关闭中,使用isShutdown();
5. 检测线程池是否已经关闭使用isTerminated();
6. 定时或者永久等待线程池关闭结束使用awaitTermination()操作
线程池Executor是异步执行任务
1. 线程池在构造前(new操作)是初始状态,一旦构造完成线程池就进入执行状态Running(接受任务会启动线程)
2. 线程池可以通过shutdown()和shutdownNow()来改变运行状态。
shutdown()是一个平缓的关闭过程,线程池停止接受新的任务,同时等待已经提交的任务执行完毕,
包括哪些进入队列还没有开始的任务,这时候线程池处于shutdown状态;
shutdownNow()是立即关闭过程,线程停止接收新任务,同时取消所有执行和已进入队列的,此时stop状态
3. 一旦shutdown()和shutdownNow()执行完毕,线程池就进入Terminated状态,此时线程池就结束了
4. awaitTermination描述的是等待线程池关闭的时间,如果等待时间线程池还没有关闭将会抛出一个超时异常
线程池执行流程
1.当前池中线程比核心数少,新建一个线程执行任务
2.核心池已满,但任务队列未满,添加到队列中
3.核心池已满,队列已满,试着创建一个新线程
示例
ThreadPoolExecutor.execute:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//1.当前池中线程比核心数少,新建一个线程执行任务
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//2.核心池已满,但任务队列未满,添加到队列中
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);
}
//3.核心池已满,队列已满,试着创建一个新线程
else if (!addWorker(command, false))
reject(command); //如果创建新线程失败了,说明线程池被关闭或者线程池完全满了,拒绝任务
}
//新门诊实施的时候初始化所用的工具,创建所有受种人模型关系
//ExecutorService pool = Executors.newCachedThreadPool();