1、使用newFixedThreadPool工厂方法创建“固定数量的线程池”的源码如下:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(
nThreads, // 核心线程数
nThreads, // 最大线程数
0L, // 线程最大空闲(Idle)时长
TimeUnit.MILLISECONDS, // 时间单位:毫秒
new LinkedBlockingQueue<Runnable>() //任务的排队队列,无界队列
);
}
2、使用newSingleThreadExecutor工厂方法创建“单线程化线程池”的源码如下:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(
1, // 核心线程数
1, // 最大线程数
0L, // 线程最大空闲(Idle)时长
TimeUnit.MILLISECONDS, // 时间单位:毫秒
new LinkedBlockingQueue<Runnable>() // 无界队列
));
}
3、使用newCachedThreadPool工厂方法创建“可缓存线程池”的源码如下:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(
0, // 核心线程数
Integer.MAX_VALUE, // 最大线程数
60L, // 线程最大空闲(Idle)时长
TimeUnit.MILLISECONDS, // 时间单位:毫秒
new SynchronousQueue<Runnable>() // 任务的排队队列,无界队列
);
}
4、使用newScheduledThreadPool工厂方法创建“可调度线程池”的源码如下:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, // 核心线程数
Integer.MAX_VALUE, // 最大线程数
0, // 线程最大空闲(Idle)时长
NANOSECONDS, // 时间单位
new DelayedWorkQueue() // 任务的排队队列
);
}
综上,使用Executors创建线程池主要的弊端如下:
(1)FixedThreadPool 和 SingleThreadPool
这两个工厂方法所创建的线程池,工作队列(任务排队的队列)的长度都为Integer.MAX_VALUE,可能会堆积大量的任务,从而导致OOM(即耗尽内存资源)。
(2)CachedThreadPool和ScheduledThreadPool
这两个工厂方法所创建的线程池允许创建的线程数量为Integer.MAX_VALUE,可能会导致创建大量的线程,从而导致OOM。
虽然Executors工厂类提供了构造线程池的便捷方法,但是对于服务器程序而言,应该杜绝使用这些便捷方法,而是直接使用线程池ThreadPoolExecutor的构造器,从而有效避免由于使用无界队列可能导致的内存资源耗尽,或者由于对线程个数不做限制而导致的CPU资源耗尽等问题。