先来看上面3种线程池的构造方法
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler
) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
从上面源码可以看出,
newSingleThreadExecutor和newFixedThreadPool的线程数量虽然是固定的,但是阻塞队列用的是new LinkedBlockingQueue()没有设置大小,如果一直往里面添加任务的话,可能会出现OOM异常。
newCachedThreadPool使用的阻塞队列虽然是new SynchronousQueue()同步队列,但是设置的最大线程数是Integer.MAX_VALUE,如果使用不当会把CPU资源耗尽。
所以上面3种创建线程池的方法都不安全,可以自定义线程池。
自定义线程池
public class ThreadPoolTest {
public static void main(String[] args) {
ExecutorService executorService = new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
int taskNum = 2;
try{
for(int i = 1;i <= taskNum;i++){
for(int i = 1;i <= taskNum;i++){
final int tp = i;
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+" ok,task" + tp);
});
}
}
}
finally {
executorService.shutdown();
}
}
}
下面通过修改任务数 taskNum 的值来查看执行结果
