一、线程池的基础总结
1、线程池的状态机器以及对应的状态流转
2、线程池如何表示状态以及线程数
3、线程池的核心参数
4、线程池的执行过程
5/1如何实现非核心线程延迟死亡?
非核心线程延迟死亡条件为:线程池处于运行状态&&当前线程数大于最大核心线程数&&获取任务超时时间keepAliveTime
5/2 如何实现核心线程一直保活?
通过阻塞队列的take()方法让线程一直等待,使得Worker的run()方法一直阻塞,直到获取到执行的任务,执行完毕任务后继续阻塞等待,使得线程生命周期一直在RUNNABLE和WAITING状态之间流转,保证核心线程一直存活
5/3 如何释放核心线程?
allowCoreThreadTimeOut这个成员变量,将这个变量设置为true就可以跟非核心线程一样,在执行keepAliveTime还未获取到执行任务时候就移出线程池
5/4非核心线程能成为核心线程吗?
创建Worker线程类并没有识别出表示一个线程是核心线程还是非核心线程
5/5线程池如何保证并发安全?
1、线程池状态和工作线程数量的并发
2、Worker容器变更的并发(添加或者删除线程)
问题1 使用AtomicInteger使用cas+volitile保证锁
微博图2对于worker集合采用的是ReetrantLock锁保证,同一个时间只有一个线程可以操作集合对象,
问题3,并发安全工作由队列BlockingQueue本身保证线程安全,内部实现使用ReetranLock实现,
5/6 线程数设置多少是合理的
5/7存放线程对象的容器为什么使用HashSet?
工作线程类Worker恶灵实现Runnable接口,他是对线程池中工作线程的抽象,ThreadsPoolexecutor对worker集合HashSet只有add和remove才做,HashSet是基于HashMap来实现的,只要Hash函数和负载因子设计的足够好,操作HashSet效率就会足够的高O(1)
5/8 结合源码介绍下线程池设计思路?
1任务处理策略:线程池优先使用核心线程来处理任务,从任务添加策略可以看出,先考虑创建核心线程处理,在考虑放到阻塞队列,然后考虑创建非核心线程,达到饱和之后使用拒绝策略
2、线程生命周期管理:通过向阻塞队列取任务的不同操作,确保线程的存活,take()保证核心线程不死,poll保证非和核心线程等待一定时间后释放
3、容量管理:线程池不区分核心线程和非核心线程,线程池期望达到corepoolSize的并发状态,并允许在不得已情况下超载,达到orepoolsize~manmumPoolSize并发状态
4、状态管理:线程池状态和数量使用ctl表示,高3位,低29位表示线程池数量。线程池对状态检查非常苛刻,几乎在所有稍微好事或者影响下一步操作正确性代码都校验ctl