为什么不建议使用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(无界队列)

正确创建线程池的方法

我们应该根据不同的业务场景,自己设置线程池参数,比如我们的内存有多大,并发量有多大,想给线程取什么样的名字,线程异常如何处理