线程池
核心线程
当jdk里新new 一个线程池时,里面是没有线程的,还没有启动;jdk和tomcat线程池不同在于,tomcat会默认new就启动核心线程数;
通过看源码:当t1线程执行完任务,又来了一个新任务,t1不会继续捕获,而是转向t5


线程池中核心线程一直存活,是因为线程执行代码中有while循环一直查看阻塞队列中是否有任务,且当任务数>=核心线程数时,任务进入阻塞队列

当阻塞队列里也放满时,再新开线程,从阻塞队列中执行优先级最高的线程,最多只能创建设置的最大线程数个数

当线程池中任务执行完毕,多余的线程会随机删除只保留核心线程个数的线程,并不是只保留原始的核心线程
线程池的五种状态
Running:接收外部的新任务,也处理队列里的任务
(用户主动调用)Shutdown:不能再接收外部新的任务,但处理队列里的任务,执行方法为shutdown(),执行完队列里的任务之后,将线程池里的线程全部关闭;
(用户主动调用)Stop:不接受外部新任务,也不处理队列里的任务,执行方法为shutdownNow(),将线程池里的线程全部关闭;
Tidying:线程池里没有线程,队列里可能有任务;然后它会自动调用terminated()方法
Terminated:线程池终止所有线程的回调方法。
线程池为什么要使用阻塞队列?
当有新的任务提交到线程池中,而线程池中的活跃线程数达到核心线程数时,线程池会将后续的task提交到阻塞队列中:
线程池创建线程需要会获得mainlock全局锁,影响并发效率,阻塞队列可以很好的缓冲
如果新任务的到达速率超过了线程池的处理速率,那么新到来的请求将累加起来,这样会耗尽资源。
线程池四大拒绝策略
触发条件:当线程池中的线程数已经达到最大线程数且任务队列已满时,线程池会调用策略来处理无法执行的新任务。
abortPolicy(中止策略):线程池的默认拒绝策略,直接抛出异常,终止任务提交(不允许任务丢失时)
CallersRunPolicy(调用者运行策略):将被拒绝的任务返回给提交任务的线程执行,缓解缓冲池的压力,但可能会导致调用线程阻塞
DiscardPolicy(丢弃策略):直接丢弃,不会抛出异常(允许部分任务丢失)
DiscardOldestPolicy(丢弃最旧任务策略):丢弃阻塞队列中等待时间最长的任务,重新提交当前任务。
线程池的最佳核心线程如何确定?
分为三步:
理论预估:对于IO密集型任务,可以多开点线程,是CPU核数的2倍多;对于CPU密集型,一般维CPU个数+1
压测验证:得到不同并发情况下CPU使用率、响应时间、错误率等数据
监控动态调整:通过监控动态调整线程池的两大参数。


浙公网安备 33010602011771号