一、线程池解决的问题
- 线程对象的重复利用
- 防止内存溢出风险,线程池中线程数、任务数可以是有限的。
- 合理的利用cpu,避免过多线程造成cpu超负荷运转
二、核心属性
- corePoolSize:线程在没有任务时,需要维持的线程数。在没有任务时维持一定量的线程,可以减少在来任务时,创建线程的时间。
- allowCoreThreadTimeOut:是否允许核心线程在指定的超时时间内,获取不到结束时结束。如果为true,在没有任务时,线程不在维持corePoolSize指定的线程数,而是逐渐递减直至为0
- keepAliveTime:获取任务的超时时间,有以下两种情况会超时获取任务,其他情况会一直阻塞获取任务
- 超过了核心线程数,且队列中有任务
- 核心线程在allowCoreThreadTimeOut=true时
- maximumPoolSize:最大线程数,超过最大线程数的线程,在获取任务阶段会直接退出,不会执行任务
- workQueue:任务队列,默认长度整型最大值,可以限制长度,防止内存溢出
三、状态
- RUNNING:初始状态
- SHUTDOWN:不在接收新任务,可能还有工作线程在继续运行,直到队列中所有任务都运行完
- STOP:不在接收新任务,所有任务线程在当前任务结束后停止,任务队列中没有运行的任务将被放弃
- TERMINATED:线程池结束
上图为状态转换图,主要涉及两个方法。
-
shutdown():将线程池置为SHUTDOWN 状态,尝试(要获取线程锁)中断工作中的线程,禁止添加新的工作线程和任务 ,如果线程池中已没有工作线程且处于SHUTDOWN 或STOP 状态,则线程池进入TERMINATED状态。
-
shutdownNow():将线程池置为 STOP 状态,中断所有的工作线程,禁止添加新的工作线程和任务;如果线程池中已没有工作线程且处于SHUTDOWN 或STOP 状态,则线程池进入TERMINATED状态。
四、获取任务流程
五、默认线程池
java提供了几个默认配置的线程池,用于不同的场景
-
Executors.newCachedThreadPool();
- 核心线程数:0
- 最大线程数:整型最大值
- 最大任务数:0
- 超时时间:60秒
- 队列:SynchronousQueue队列(没有容量)
- 特点:每添加一个任务,就会获取或新建一个线程,线程任务结束后会在60秒后结束线程
-
Executors.newSingleThreadExecutor()
- 核心线程数:1
- 最大线程数:1
- 最大任务数: 整型最大值
- 超时时间:0秒
- 队列:LinkedBlockingQueue
- 特点:最多存在一个线程
-
Executors.newFixedThreadExecutor(线程数 n)
- 核心线程数:n
- 最大线程数:n
- 最大任务数: 整型最大值
- 超时时间:0秒
- 队列:LinkedBlockingQueue
- 特点:最多存在n个线程