ThreadPoolExecutor是一个线程池,最多可使用7个参数来控制线程池的生成。
使用线程池可以避免创建和销毁线程的资源损耗,提高响应速度,并且可以管理线程池中线程的数量和状态等等。
阿里巴巴手册中也推荐使用该线程池,因为Executors创建缓存线程池时,最大线程数是Integer.MAX_VALUE
,可能导致堆栈溢出。而且使用ThreadPoolExecutor创建线程池可以让开发者更好理解线程池原理。
无须重复创建和销毁线程,减少了线程创建和销毁造成的资源消耗。
创建好的线程会驻留在线程池中,无需创建新线程执行任务,因而提高了响应速度。
线程池可以控制线程的数量,可以选择拒绝策略,可以监控和管理线程的状态,控制并发量等等。
这些都是自己创建线程难以做到的。
线程池常驻线程数量
最大可存在的线程数量
非核心线程空闲时,可以停留的时间
非核心线程空闲时,可以停留的时间的单位
线程都在使用中时,可以将任务保存在阻塞队列中,可以设置队列的长度。
可以选择创建线程的工厂
当线程池无法存放更多任务时,处理这些过多的任务的策略
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//判断工作线程数是否小于核心线程数
if (workerCountOf(c) < corePoolSize) {
//是,创建一个新线程
if (addWorker(command, true))
return;
c = ctl.get();
}
//否,将任务尝试添加到阻塞队列中,如果队列满了则会添加失败。
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
//判断线程池状态是否在运行中,不在运行中时,删除该任务
if (! isRunning(recheck) && remove(command))
//不在运行中时,执行拒绝策略
reject(command);
//判断工作线程数是否为0
else if (workerCountOf(recheck) == 0)
//为0的场合,尝试创建新线程
addWorker(null, false);
}
//添加失败的场合,尝试创建一个新线程
else if (!addWorker(command, false))
//如果添加失败,执行拒绝策略
reject(command);
}
一个固定数量的线程池,可以通过传入的参数int nThreads
来控制线程池的线程数量。(核心线程数和最大线程数相同)
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
一个线程数只有1的线程池。可以保证任务的顺序执行。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
缓存线程池,新创建的线程会在该线程池中缓存60秒。可以提高短期异步任务的性能。
注意,最大线程数是Integer.MAX_VALUE
,高并发的场合下,可能会创建大量线程。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
定时任务线程池,使用该线程池可以定时执行任务。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}