文章目录
前言
本文主要介绍线程池的相关用法和基础知识一、为什么要用线程池
1. 不停创建线程的缺点
- 反复创建线程,开销大
- 过多线程占用太多内存
- 解决思路:用少量的线程反复的执行任务
2. 线程池的好处
- 加快响应速度
- 合理利用CPU和内存
- 统一管理
3. 线程池适用场景
- 服务器介绍大量请求
- 需要创建5个以上的线程
二、线程池中的参数
- corePoolSize:线程池初始化后,里面没有线程,这时候来一个任务就会先创建一个线程,会创建corePoolSize个
- maxPoolSize:可能核心线程不够用了,那就可以额外增加一些线程,但是有一个上限:maxPoolSize
添加线程的规则
- 当线程数小于corePoolSize,及时其他线程处于空闲状态,也会创建一个新线程来运行新任务
- 当线程数打印等于corePoolSize但小于MaxPoolSize,就将任务放入队列
- 当队列已满,并且线程数小于maxPoolSize,则创建一个新线程来运行任务
- 当队列已满,并且线程数大于或等于maxPoolSize,则拒绝任务
三、四种线程池
1. newFixedThreadPool
使用的是LinkedBlockingQueue无界队列:可以一直接收任务,存到队列中,可能会导致OOM
2. newSingleThreadExecutor
这里也是LinkedBlockingQueue,但是它的corePoolSize和maxPoolSize都是1,也就是整个线程池中只有1个线程,无法执行的任务都放在队列里面。
3. newCachedThreadPool
它可以创建无限个线程,有存活时间,队列使用的是SynchronousQueue同步队列,也就是它不会缓存任何任务,当一个任务来了,就要阻塞等待线程去处理。
4. ScheduledThreadPool
使用方式:
线程池中的线程数设定为多少最合适?
线程数=CPU核心数*(1+平均等待时间 /平均工作时间)
四、停止线程池
- shutdown:线程池等待所有任务执行完之后才结束,拒绝接收新提交的任务
- isShutdown:判断是否已经停止
- isTerminated:判断是否完全终止
- awaitTermination:当前线程会被阻塞,直到线程池状态变为TERMINATED才返回,或者等待时间超时才返回,用来测试一段时间内线程池状态
- shutdownNow:线程池拒接收新提交的任务,同时立马关闭线程池,线程池里的任务不再执行。
五、拒绝策略
当任务过多时,线程池会拒绝,有四种拒绝策略
- AbortPolicy:抛出异常
- DiscardPolicy: 默默丢弃,不抛出异常
- DiscardOldestPolicy: 调用poll丢弃一个任务,执行当前任务
- CallerRunsPolicy:使用调用者所在线程来运行任务(可以让主线程执行任务,进而抑制主线程提交任务)
六、源码
创建线程
线程池执行任务: