为什么不建议使用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(无界队列) |
正确创建线程池的方法
我们应该根据不同的业务场景,自己设置线程池参数,比如我们的内存有多大,并发量有多大,想给线程取什么样的名字,线程异常如何处理