java中多数利用Executors创建不同的线程池满足不同场景的需求
- newFixedThreadPool(int nThreads) 指定工作线程数量的线程池
- newCachedThreadPool() 处理大量短时间工作任务的线程池
- 试图缓存线程并重用,当无缓存线程可用时,就会创建新的工作线程
- 如果闲置的线程超过阈值,一般为60s,则会被终止并移除缓存
- 系统长时间闲置的时候,不会消耗什么资源
- newSingleThreadExecutor() 创建唯一的工作线程来执行任务,若异常退出,则会有另一个线程取代它
- newSingleThreadScheduledExecutor()与newScheduledThreadPool(int corePoolSize)定时或者周期性的工作调度,俩者的区别在于单一工作线程或者多线程执行
- newWorkStealingPool() 内部构建ForkJoinPool,利用working-stealing算法,并行的处理任务,不保证处理顺序
Fork/Join框架
其原理是将大任务分割成若干小任务并行执行,最终汇总每个小任务执行结果后得到大任务结果的框架
Work-Stealing算法:某个线程从其他队列里窃取任务来执行,一般使用双端队列,窃取任务的时候从队列尾部进行执行
为什么引入线程池?
- 降低资源损耗
- 提高线程的可管理性
- 实现线程复用
创建以上5种不同线程池的底层都是new的ThreadPoolExecutor
java线程池的工作流程
线程池的状态
- RUNNING:能接受新的任务,并处理阻塞队列中的任务
- SHUTDOWN:不再接收新提交任务,可以处理存量任务
- STOP:不再接收新提交任务,也不处理存量任务
- TIDYING:所有任务都终止
- TERMINATED:terminated()方法执行后到该状态
线程池数目的设置规则
线程池Submit与execute的区别
- submit方法可以获得线程返回值
- excute方法会抛出异常。sumbit方法不会抛出异常。除非你调用Future.get()。