文章目录
- ThreadPoolExecutor
- 线程池状态
- 构造方法
- Executors 工厂方法
- newFixedThreadPool
- newCachedThreadPool
- newSingleThreadExecutor
- 提交任务方法
- 关闭任务方法
ThreadPoolExecutor
线程池状态
线程池用高三位表示状态,第一位为符号位。
TERMINATED > TIDYING > STOP > SHUTDOWN > RUNNING
构造方法
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;
}
- corePoolSize 核心线程数目
- maximumPoolSize 最大线程数目
- keepAliveTime 生存时间 - 针对救急线程
- unit 时间单位 - 针对救急线程
- workQueue 阻塞队列
- threadFactory 线程工厂
- handler 拒绝策略
任务会先创建核心线程执行,若核心线程到达核心数,任务进入阻塞队列(任务队列),若阻塞队列也满了,则启用急救线程执行任务,若达到最大线程数,那么才会启用拒绝策略,急救线程在一段时间没有执行任务会自行关闭。
Executors 工厂方法
帮助我们快速构建想要的线程池,不用配置那么多参数。
newFixedThreadPool
固定线程的线程池
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
特点:
- 核心线程数 = 最大线程数(救急线程)。
- 无界队列,可以放入任意多任务。
- 阻塞队列是无界的,可以放任意数量的任务。
适用于任务量已知,相对耗时的任务。
newCachedThreadPool
带缓冲的线程池
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
特点:
- 核心线程数是 0,最大线程数是 Integer.MAX_VALUE。
- 创建的全部都是救急线程(60s 后可以回收)
- 救急线程可以无限创建。
- 队列采用了SynchronousQueue(同步队列),没有容量,有线程去取才能放入,所以叫同步的队列。
适合任务数比较密集,但每个任务执行时间较短的情况。
newSingleThreadExecutor
单线程的线程池
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
特点:
线程数固定为 1,任务数多于 1 时,会放入无界队列排队。
任务执行完毕,这唯一的线程也不会被释放。
和自己创建一个线程来工作的区别:
- 自己创建一个单线程串行执行任务,如果任务执行失败而终止那么没有任何补救措施,而线程池还会新建一个线程,保证池的正常工作。
和Executors.newFixedThreadPool(1)的区别:
- Executors.newSingleThreadExecutor() 线程个数始终为1,不能修改。FinalizableDelegatedExecutorService 应用的是装饰器模式,只对外暴露了 ExecutorService 接口,因此不能调用 ThreadPoolExecutor 中特有的方法
- Executors.newFixedThreadPool(1) 初始时为1,以后还可以修改。
对外暴露的是 ThreadPoolExecutor 对象,可以强转后调用 setCorePoolSize 等方法进行修改
提交任务方法
// 执行任务
void execute(Runnable command);
// 用Future 获得任务执行结果,保护性暂停,主线程输出结果时,阻塞,直到返回结果
<T> Future<T> submit(Callable<T> task);
// 提交集合中所有任务
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
// 提交集合中所有任务,带超时时间
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
// 交集合中所有任务, 只要有一个任务完成,返回结果,其他的任务取消
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
// 交集合中所有任务, 只要有一个任务完成,返回结果,其他的任务取消, 带超时时间
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
关闭任务方法
void shutdown();
线程池状态变为 SHUTDOWN
- 不会接收新任务
- 但已提交任务会执行完
- 此方法不会阻塞调用线程的执行
List<Runnable> shutdownNow();
线程池状态变为 STOP
- 不会接收新任务
- 会将队列中的任务返回
- 并用 interrupt 的方式中断正在执行的任务
// 不在RUNNING状态的线程池,就返回 true
boolean isShutdown();
// 线程池状态是否是TERMINATED
boolean isTerminated();
// 调用 shutdown 后,由于调用线程并不会等待所有任务运行结束,因此如果它想在线程池 TERMINATED 后做些事情,可以利用此方法等待
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;