关于线程池的连环21问
1、为什么会有线程池?
2、简单手写一个线程池?
3、为什么要把任务先放在任务队列里面,而不是把线程先拉满到最大线程数?
4、线程池如何动态修改核心线程数和最大线程数?
5、如果你是 JDK 设计者,如何设计?
6、如果要让你设计一个线程池,你要怎么设计?
7、你是如何理解核心线程的?
8、你是怎么理解 KeepAliveTime 的?
9、那 workQueue 有什么用?
10、你是如何理解拒绝策略的?
11、你说你看过源码,那你肯定知道线程池里的 ctl 是干嘛的咯?
12、你知道线程池有几种状态吗?
13、你知道线程池的状态是如何变迁的吗?
14、如何修改原生线程池,使得可以先拉满线程数再入任务队列排队?
15、Tomcat 中的定制化线程池实现 如果线程池中的线程在执行任务的时候,抛异常了,会怎么样?
16、原生线程池的核心线程一定伴随着任务慢慢创建的吗?
17、线程池的核心线程在空闲的时候一定不会被回收吗?
18、corePoolSize=0会怎么样?
19、线程池创建之后,会立即创建核心线程么?
20、核心线程永远不会销毁么?
21、空闲线程过多会有什么问题?
下面将对理解线程池的原理、源码介绍,并逐步回答上述经典问题。当然,如果您对线程池的源码熟记于心,则就没看下去的必要。
2.https://mp.weixin.qq.com/s/7fluKiSaMnhfmHBNOOBjOQ
最佳实践总结
【强制】使用ThreadPoolExecutor的构造函数声明线程池,避免使用Executors类的 newFixedThreadPool和newCachedThreadPool。
【强制】 创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。即threadFactory参数要构造好。
【建议】建议不同类别的业务用不同的线程池。
【建议】CPU密集型任务(N+1):这种任务消耗的主要是CPU资源,可以将线程数设置为N(CPU核心数)+1,比CPU核心数多出来的一个线程是为了防止线程偶发的缺页中断,或者其它原因导致的任务暂停而带来的影响。一旦任务暂停,CPU就会处于空闲状态,而在这种情况下多出来的一个线程就可以充分利用CPU的空闲时间。
【建议】I/O密集型任务(2N):这种任务应用起来,系统会用大部分的时间来处理I/O交互,而线程在处理I/O的时间段内不会占用CPU来处理,这时就可以将CPU交出给其它线程使用。因此在I/O密集型任务的应用中,我们可以多配置一些线程,具体的计算方法是2N。
【建议】workQueue不要使用无界队列,尽量使用有界队列。避免大量任务等待,造成OOM。
【建议】如果是资源紧张的应用,使用allowsCoreThreadTimeOut可以提高资源利用率。
【建议】虽然使用线程池有多种异常处理的方式,但在任务代码中,使用try-catch最通用,也能给不同任务的异常处理做精细化。
【建议】对于资源紧张的应用,如果担心线程池资源使用不当,可以利用ThreadPoolExecutor的API实现简单的监控,然后进行分析和优化。