利用Executors创建不同的线程池
- newFixedThreadPool(int nThreads):指定工作数量的线程池
- newCachedThreadPool():处理大量短时间工作任务的线程池
1). 试图缓存线程并重用 ,当无缓存线程可重用时,会创建新的工作线程;
2). 如果线程时间过长,会被终止并移除缓存
3). 系统长时间闲置的时候,不会消耗什么资源
- newSingleThreadExecutors():创建唯一的工作线程来执行任务,如果线程异常结束,会有另一个线程取代
- newSingleThreadScheduledExecutors()与newSingleThreadScheduledPool(int corePoolSize) :定时或周期性的工作调度,前者为单一线程工作,异常结束时,会有另一个线程取代,后者为多个线程工作
- newWorkStealingPool():内部会构建ForkJoinPool,利用work-stealing算法,并行的处理任务,不保证处理顺序,适用于把一个问题可拆解为n个小问题
注意:以上都属于Executor框架体系
Fork/Join框架:把大任务分割成若干个小任务进行,最终把每个小任务的结果汇得到大任务结果的(原理和map-reduce)相同
work-stealing算法:某个线程从其他队列里窃取任务来执行。( work-stealing算法详细解释)
使用线程池的好处
- 降低资源消耗,通过重复利用已创建的线程
- 提高线程的可管理性
Executor框架
Executor框架:提供一种将任务提交和运行分离的机制
JUC的三个Executor接口
1. Executor:执行新任务的简单接口,将任务提交和执行进行解耦(Executor中只有一个方法)
- ExecutorServicee:扩展了Executor具备管理执行器和任务生命周期的方法,提交任务机制更加完善
- ScheduledExecutorService:扩展了ExecutorService,支持
Future和定期执行任务
大多数场景直接用Executors但是有时还会用用到ThreadPoolExecutor
ThreadPoolExecutor的构造函数中的参数
- corePoolSize:核心线程数量(线程池中常驻线程数量)
- maximumPoolSize:线程不够用时能够创建的最大线程数
- keepAliveTime:多余的线程空闲超过一段时间,会被销毁
- workQueue:任务等待队列
- unit:时间单位
- threadFactory:创建新线程,默认使用Executors.defaultThreadFactory(),此时线程优先级相同
- handler:线程池饱和策略(任务等待队列满了的时候,已经没有地方可一容纳该任务时执行的策略)
四种策略
- AbortPolicy:直接抛异常,默认策略
- CallerRunsPolicy:用调用者所在的线程来执行任务
- DiscardOldestPolicy:丢弃队列中靠最前的任务,并执行当前任务
- DiscardPolicy:直接丢弃任务
- 通过实现RejectedExecutionHandler接口的自定义handler
新任务execute执行后的判断(深入了解)
(假设corePoolSize=3,maximumPoolSize = 5,workQueue容量为2)
1. 当工作线程数量小于3时,就会创建线程处理任务
2. 当线程池数大于等于3时(小于5),只有当队列满的时候才会创建新线程
3. 如果线程池的线程数等于了5时,且等候队列已经慢的时候,开始使用指定的拒绝策略
线程池的状态
- running:可接受新提交的任务,并且也能处理队列中的任务
- shutdown:不在接受新提交的任务,可以出路队列中的任务
- stop:不再接受新提交的任务,也不处理队里中的任务了,会中断正在执行任务的线程
- tidying:所有任务都已经终止
- terminated:terminated方法执行后进入改状态