线程池:线程池和数据库连接池非常类似,可以统一管理和维护线程,减少没有必要的开销。
1.为什么需要使用线程池
因为频繁开启线程和停止线程,线程需要从新被cpu从就绪到运行状态调度,需要发生cpu上下文切换,效率非常低。
线程池是复用机制
提前创建好一些固定的线程数一致在运行状态实现复用,从而可以减少就绪到运行状态的切换。

2.哪些地方会用到线程池
实际开发中禁止使用new线程
必须使用线程池来维护和创建线程池
常用 发送邮件 发送短信的时候
3.线程池有哪些好处
核心点:复用机制 提前创建好固定的线程一直在运行状态 实现复用 限制线程创建数量
1」降低资源消耗
2」提高响应速度
3」提高线程的可管理性
4」提供更多更强大的功能;比如说 延时定时线程池
4.线程池的创建方式
Executors.newCachedThreadPool() 可缓存线程池
Executors.newFixedThreadPool() 可定长度
Executors.newScheduledThreadPool() 可定时
Executors.newSingleThreadExecutor() 单例
底层都是基于ThreadPoolExecutor 构造函数封装
5.线程池底层如何实现复用
- 提前创建好固定的线程一直在运行状态 -----死循环实现
- 提交的线程任务缓存到一个并发队列集合中,交给正在运行的线程执行
- 正在运行的线程就从队列中获取该任务执行
6.ThreadPoolExecutor核心参数
- corePoolSize:核心线程数
- maximumPoolSize:最大线程数
- keepAliveTime:超出corePoolSize后创建的线程存活时间
- unit: keepAliveTime的时间单位
- workQueue: 任务队列 用于保存待执行的任务
- threadFactory: 线程池内部创建线程多用的工厂
- handler: 任务无法执行时的处理器
7.线程池创建的线程会一直在运行状态吗?
不会。 我们可以配置超出核心线程数后创建的线程的存活时间例如为60s
在60s内没有核心线程一直没有任务执行,则会停止该线程。
8.线程池底层ThreadPoolExecutor原理实现
专业术语
- 当线程数小于核心线程数时,创建线程;
- 当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列;
- 当线程数大于等于核心线程数,且任务队列已满时
- 若线程数小于最大线程数,创建线程
- 若线程数等于最大线程数,抛出异常,拒绝任务。
9.线程队列满了任务会丢失吗
如果队列满了,且任务总数>最大线程数则当前线程走拒绝策略。
可以自定义拒绝异常,将该任务缓存到redis,本地文件,mysql中后期项目启动实现补偿
10.线程池拒绝策略有哪些
new ThreadPoolExecutor.AbortPolicy() 队列满了 不处理 抛出异常
new ThreadPoolExecutor.CallerRunsPolicy() 返回到主线程 去帮忙执行
new ThreadPoolExecutor.DiscardPolicy() 队列满了 丢掉任务 不抛出异常
new ThreadPoolExecutor.DiscardOldestPolicy() 队列满了 任务和最早的线程中争抢资源 不抛出异常
11.为什么阿里巴巴不建议使用Executors
因为默认的Executors线程池底层是基于ThreadPoolExecutor构造函数封装的,采用误解队列存放缓存任务,会无限缓存任务容易发生内存溢出,会导致我们最大线程会失效。
2626

被折叠的 条评论
为什么被折叠?



