线程池面试题
约 912 字大约 3 分钟
线程池面试题
线程池都有哪些参数?
这个问题是很好回答的,只要自己画过流程图,都能说出来,今天使用不同角度写一下每个参数的意义和容易错的点。
- 核心线程
- 最大线程
- 设置队列
- 拒绝策略
- 回收时间限制
core
核心线程,在接收请求时处理问题核心,当线程小于核心线程时,直接增加线程,一般情况下不会设置很大。
max
最大数量线程,当队列满的时候创建的最大线程,如果线程满了,处理任务数据还解决不了的话就需要考虑如何丢失任务策略。 而max不要使用Integer.MAX_VALUE。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
提示
如果队列使用无边界队列就会导致core线程满了之后,任务进入到队列里面,而队列是无边界的,则不会在创建max - core
这部分线程。
- xss设置了大小,当线程数量很多的时候也会导致oom;
- 线程数量很多的时候,队列加锁情况下会导致竞态加剧,参考非公平锁性能比公平锁要高。
丢弃任务策略
丢弃策略是为了保护服务可用,来看下redis最新也支持了内存淘汰策略,其实这里一样,都是为了保护服务而创建的,其实这里的淘汰策略和redis目的是一致的。
提示
- volatile-lru(least recently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
- volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
- volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
- allkeys-lru(least recently used):当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)
- allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!
4.0 版本后增加以下两种:
- volatile-lfu(least frequently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰
- allkeys-lfu(least frequently used):当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key
队列
我们知道线程最主要的作用就是削峰填谷,kafka也是,队列很重要。
- 考虑如果队列可以无限扩张,一直扩张到无法分配内存,这时候服务会怎么样,会oom;
- 考虑如果队列可以无限扩展,一直打不满,则就不会扩张到max,削峰填谷的能力被大大削弱。
回收时间
资源回收。
结论
- 回收机制
- 线程资源回收
- 任务策略拒绝
- 内存管理
- 线程数量保证不会oom(xss * count > heap)
- 队列不会无限扩张导致oom
- 削峰填谷
- 队列
- 处理任务能力,线程数量不可太小,也不可太大