线程池任务执行逻辑思考
在理解线程池的执行逻辑的时候,有关于是先提交入队列还是先创建非核心线程的时候总会混淆。先看下实际的逻辑,盗图(https://mp.weixin.qq.com/s/Nv1ITA_i8Q64XLj7nC0yCg):
线程池提交任务时的执行逻辑实际情况是:在核心线程数已满的情况下,如果任务缓冲队列已满才会创建非核心线程;如果队列未满时,任务将会提交入队列排队。
对比下如果优先创建非核心线程会有啥问题,权衡利弊:
优先入队列的优点:
1. 池中的线程循环取队列里的任务,如果队列没满就创建非核心线程,会出现队列为空就创建非核心线程的情况,将导致反复创建和销毁非核心线程的开销;
2. 队列空间将大概率浪费,只有当最大线程数都处理不完的任务量时才有可能利用这些空间
3. 待完善~
优先入队列的缺点:
1. 任务可能有少许延迟(在队列排队呢)
2. 会出现插队现象,队列满了时,创建的非核心线程直接执行了后到来的任务;
3. 待完善~
综合权衡的话,少许延迟可以接受,任务之间通常没有先后依赖,优先入队列性能开销及逻辑更加合理。
补充:
jdk原生的线程池确实完善(如上图的执行逻辑),但是这种比较适合cpu密集型的任务,如果是IO密集型的话,线程不一定都在运行,很可能是阻塞的,这样的效率会比较底下;所以针对IO密集型的任务,还是优先创建线程比较靠谱。
所以可以看到tomcat(网络IO型)在jdk原生线程池的基础上做了扩展:在向队列添加任务时,判断待执行的任务数(原子的计数变量:submittedCount)大于当前线程数,则直接返回false,优先创建非核心线程了;参考
或者可以使用jdk的keepAliveTime使非核心线程永久不失效,不过可能浪费资源~
总结:jdk原生线程池执行逻辑是否合理,it depends! 如果是cpu密集型,合理;IO密集型可以优化。