为什么不建议使用Executors类创建线程池
Executors
是一个工具类,可以帮助我们快速创建线程池,但《阿里巴巴开发手册》却说不建议使用Executors
来创建线程池,这是为什么呢?
newFixedThreadPool
由于传进去的 LinkedBlockingQueue
是一个无界队列,没有容量上限,所以当请求数越来越多,并且无法及时处理完的时候,就会不停的向 LinkedBlockingQueue
塞进线程,直至内存溢出 OOM
newSingleThreadExecutor
这个和 newFixedThreadPool
的原理一样,只不过核心线程数和最大线程数都设置成了 1,但是由于同样使用了 LinkedBlockingQueue
,所以也会因为大量线程堆积导致 OOM
newCachedThreadPool
这个线程池使用了 SynchronousQueue
队列,这个队列可以理解为一个空队列,有任务进来,当前又没有空闲线程,那么就直接创建线程去执行,其特点是当一段时间没有任务进来,线程空置超过一定时间(默认是 60 s),线程就会回收。因为其最大线程数设置的值为 Integer.MAX_VALUE
,所以也会因为不断创建线程而导致 OOM
newScheduledThreadPool
这是一个支持定时及周期性执行任务的线程池,其底层使用了 DelayedWorkQueue
其最大线程数也是 Integer.MAX_VALUE
,同样有 OOM 的风险
四种线程池的对比
参数 | newFixedThreadPool | newSingleThreadExecutor | newCachedThreadPool | newScheduledThreadPool |
---|---|---|---|---|
corePoolSize | 参数指定 | 1 | 0 | 参数指定 |
maximumPoolSize | 等于 corePoolSize | 1 | Integer.MAX_VALUE | Integer.MAX_VALUE |
keepAliveTime | 0s | 0s | 60s | 0s |
workQueue | LinkedBlockingQueue(无界队列) | LinkedBlockingQueue(无界队列) | SynchronousQueue(无空间队列) | DelayedWorkQueue(无界队列) |
正确创建线程池的方法
我们应该根据不同的业务场景,自己设置线程池参数,比如我们的内存有多大,并发量有多大,想给线程取什么样的名字,线程异常如何处理