答:会存在内存溢出的风险。因为Executors中的核心方法,默认创建线程池的最大线程数是Integer.MAX_VALUE即int类型的最大值2^32-1,最大线程数允许这么多,几乎相当于不限制线程数,而这样的后果就是,如果瞬间请求量非常大,如果达到这个上限,没有任何服务器能够继续工作,肯定会抛出OOM异常。
Executors核心的方法有五个:
1)Executors.newCachedThreadPool
这个方法中maximumPoolSize最大可以至Integer.MAX_VALUE,是高度可伸缩的线程池,如果达到这个上限,相信没有任何服务器能够继续工作,肯定会抛出OOM异常。keepAliveTime默认为60秒,工作线程处于空闲状态,则回收工作线程。如果任务数量增加,再次创建出新线程处理任务。
2)Executors.newScheduledThreadPool
这个方法中maximumPoolSize最大可以至Integer.MAX_VALUE,也是是高度可伸缩的线程池,同样存在OOM问题。
它支持定时以及周期性的执行任务,它与newCachedThreadPool的区别是不回收工作线程。
3)Executors.newSingleThreadExecutor
作用:创建一个单线程的线程池,相当于单线程串行执行所有任务,保证按任务的提交顺序依次执行。当瞬间请求量非常大也会存在OOM问题。
4)Executors.newFixedThreadPool
输入的参数即是固定线程数,既是核心线程数也是最大线程数,不存在空闲线程,所以keepAliveTime等于0
这里,输入的队列没有指明长度,其中LinkedBlockingQueue的构造方法:
LinkedBlockingQueue是无界队列,最大长度也是Integer.MAX_VALUE即int类型的最大值2^32-1,使用这样的无界队列,如果瞬间请求量非常大,会有OOM风险。
5)Executors.newWorkStealingPool
JDK8引入的,作用:创建持有足够线程的线程池支持给定的并行度,并通过使用多个队列减少竞争,此构造方法中把CPU数量设置为默认的并行度:
禁止直接使用Executors创建线程池原因:
Executors.newCachedThreadPool和Executors.newScheduledThreadPool两个方法最大线程数为Integer.MAX_VALUE,如果达到上限,没有任务服务器可以继续工作,肯定会抛出OOM异常。
Executors.newSingleThreadExecutor和Executors.newFixedThreadPool两个方法的workQueue参数为new LinkedBlockingQueue<Runnable>(),容量为Integer.MAX_VALUE,如果瞬间请求非常大,会有OOM风险。
总结:以上5个核心方法除
Executors.newWorkStealingPool方法之外,其他方法都有OOM风险。