1.JDK Executors线程池
2.JDK提供哪些默认的实现
- newFixedThreadPool
- newCachedThreadPool
- newSingleThreadExecutor
3.为什么不允许使用默认实现
会OOM
4.介绍一下自定义线程池的几个常用参数,几个参数的值怎么定
5.线程池里的任务是IO密集型还是计算密集型
6.io密集型,CPU核数+1。为什么要加1?
当有线程阻塞(sleep、IO操作、等待锁)时,CPU释放,多出来的线程就可以充分利用CPU时间,相当于备份线程。可能还得考虑其他应用的线程配置情况
7.线程池满了怎么办
拒绝策略
8.线程池参数动态化
1)为什么要动态化?
因为不同时刻流量是不同的,流量不均衡
2)如何动态化?
将线程池的参数(如核心线程池、最大线程数、阻塞队列长度)迁移到分布式配置中心,实现线程池参数可配置和即时生效
3)动态化原理
3.1)setCorePoolSize
在运行期线程池使用方调用此方法设置核心线程数量,会覆盖原始值。并且会比较当前值和原始值,做不同动作
- 当前值小于工作线程数,证明有多余线程,中断空闲线程,回收
- 当前值大于原始值,且当前队列有任务待执行,新建worker线程,执行任务
3.2)setMaximunPoolSize
设置最大线程数量。 - 校验参数合法性
- 覆盖原来的值
- 判断当前工作线程数是否大于最大线程数,是则向空闲线程发起中断请求
4)动态设置需要注意的地方
- 可能会出现无效的情况,就是设置核心线程数的时候
- getTask()获取任务时,会判断,如果工作线程数大于最大线程数,就会对工作线程数量进行-1操作,然后返回null。即没有获取到task,就会清理该任务
- 解决:设置核心线程数的时候,同时设置最大线程数。如果调整之后活动线程数设置的值太大了,低峰期怎么办?当allowCoreThreadTimeOut设置为true时,核心线程在空闲时也会被回收。相当于线程池自动动态修改
5)动态指定队列长度
- 因为LinkedBlockQueue的capacity是final修饰的,所以我们可以拷贝一份LinkedBlockingQueue的代码。修改capacity为非final,并提供对应的get/set方法
- 在程序里用新的队列
线程池被创建后,就有线程吗?如果没有,可以对线程池进行预热吗?
线程池被创建后,没有任务时是没有线程的。预热有两个方法
全部启动:prestartAllCoreThreads()方法
仅启动一个:prestartCoreThread()方法
核心线程数会被回收吗需要什么设置?
默认是不能的。如果需要回收,则调用allowCoreThreadTimeOut(boolean value)