线程池的原理
ThreadPoolExecutor
线程池:有几个比较重要的参数
核心线程池的数量:io密集型线程设置多一点(2*N) cpu密集型 设置少一点 (N+1)
依赖数据库连接池的任务,因为线程提交SQL后需要等待数据库返回结果,等待的时间越长,则CPU空闲时间就越长,那么线程数应该设置得越大,这样才能更好地利用CPU。
keepAliveTime:非核心线程,空闲多长时间后被销毁 unit:时间的单位
BlockingQueue:阻塞队列的实现
常用的有:·ArrayBlockingQueue ·LinkedBlockingQueue PriorityBlockingQueue
建议使用有界队列 那样不至于把内存占满才报错,影响其他服务,使用有界队列,队列满了,就报错了,方便排查
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
饱和策略
·AbortPolicy:直接抛出异常。
CallerRunsPolicy:只用调用者所在线程来运行任务。
DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。 ·
DiscardPolicy:不处理,丢弃掉。
当然,也可以根据应用场景需要来实现RejectedExecutionHandler接口自定义策略。如记录 日志或持久化存储不能处理的任务
线程池满了怎么办?
1:如果不是,那说明,代码设计的有问题,分析线程池为什么满了?因为有的任务是IO型的(比如牵扯数据库连接),有的cpu计算型的,就是说不同任务,花费的时间差的比较多,IO型的任务,把线程阻塞了,使得
cpu型的任务都堆积在阻塞队列了,阻塞队列满了,抛出异常等。我们可以尝试多建几个不同类型的线程池,分别处理cpu密集型的任务(核心线程=N+1),处理IO型的任务(比如核心线程=2*N)
2:首先考虑是不是用户并发量,确实太大了,再多搞点机器
3:面试官给我了一个fullgc的角度去思考
4:一般rt抖动会导致你的线程池满?
5:只有一台线程池满和全部集群线程池满了如何去解决
我是这样想:
1:
阻塞队列设成无界的,就是把任务存在队列里,即内存里,慢慢消化处理
2:把请求持久化到硬盘里,慢慢消化
6:快速止血问题排查?
核心线程也有可能被销毁
1:一个就是allowCoreThreadTimeOut参数 这个如果为true 则会给核心线程数设置超时等待时间 如果超过时间了 就会销毁
默认是false 这个参数不是这次的重点 因为默认是关闭的 一般不会特意开启
2:还有一种情况是,任务执行时抛出异常了,这会导致线程重建
ThreadPoolExecutor
final void runWorker(Worker w) {
Runnable task = w.firstTask;
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
try {
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);//如果能执行这一句,就说明,一定有异常抛出来了
}
}
private void processWorkerExit(Worker w, boolean completedAbruptly) {
try {
completedTaskCount += w.completedTasks;
//删除当前线程
workers.remove(w);
} finally {
mainLock.unlock();
}
if (runStateLessThan(c, STOP)) {
//创建一个空的工作线程
addWorker(null, false);
}
}