聊聊高并发(三十九)解析java.util.concurrent各个组件(十五) 理解ExecutorService接口的设计
2015-06-26 17:22
881 查看
上一篇讲了Executor接口的设计,目的是将任务的执行和任务的提交解耦,可以隐藏任务的执行策略。这篇说说ExecutorService接口。它扩展了Executor接口,对Executor的生命周期进行管理,并进行了进一步的扩展。
Executor负责执行任务。它的生命周期有3个:运行,关闭和已终止。在运行的任何时刻,有些 任务可能已经完成,有些可能正在运行,有些可能正在队列中等待执行。所以如果要关闭Executor的话,就有多种方式,比如优雅平滑的关闭,当执行关闭时就不在接受新的任务请求,并且等到已运行的任务执行完成再关闭Executor;比如最粗暴的关闭,直接关闭Executor,不管在运行的任务是否执行完毕。
1. shutdown()方法是优雅关闭的方式
2. shutdownNow()是粗暴关闭的方式,它返回一个还未开始执行的任务的列表。对于正在运行的任务,它采用Thread.interrupt()的方式来取消任务。如果任务不响应线程的中断,那么这个任务可能会一直执行。
3. awaitTermination()方法会等待一段时间再来终止执行的任务
ExecutorService的JavaDoc里面的这段代码展示了两阶段来关闭Executor的方式
1. 先用shutdown()来停止接受新的任务
2. 再用awaitTermination()方法等待一段时间来让运行的任务执行完毕,再shutdownNow()强制关闭(采用Thread.interrupt()的方式)。再次awaitTermination()等待一段时间,这里是针对上面说的不响应Thread.interrupt()的任务。如果还没有terminated,就提示Executor没有完成关闭,还有线程在执行任务。
除了关闭Executor和检查Executor状态的方法外,ExecutorService还定义了一系列的submit()和invoke()来支持任务异步执行和批量执行。
submit()方法支持Callable接口和普通的Runnable接口,它的目的是返回一个Future对象来支持任务的异步执行。调用者可以通过Future对象来检查任务的执行状态。后面会具体介绍Future相关的内容。
invokeAll()和invokeAny()提供了批量执行任务的接口。
Executor负责执行任务。它的生命周期有3个:运行,关闭和已终止。在运行的任何时刻,有些 任务可能已经完成,有些可能正在运行,有些可能正在队列中等待执行。所以如果要关闭Executor的话,就有多种方式,比如优雅平滑的关闭,当执行关闭时就不在接受新的任务请求,并且等到已运行的任务执行完成再关闭Executor;比如最粗暴的关闭,直接关闭Executor,不管在运行的任务是否执行完毕。
1. shutdown()方法是优雅关闭的方式
2. shutdownNow()是粗暴关闭的方式,它返回一个还未开始执行的任务的列表。对于正在运行的任务,它采用Thread.interrupt()的方式来取消任务。如果任务不响应线程的中断,那么这个任务可能会一直执行。
3. awaitTermination()方法会等待一段时间再来终止执行的任务
public interface ExecutorService extends Executor { void shutdown(); List<Runnable> shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; <T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable 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; }
ExecutorService的JavaDoc里面的这段代码展示了两阶段来关闭Executor的方式
1. 先用shutdown()来停止接受新的任务
2. 再用awaitTermination()方法等待一段时间来让运行的任务执行完毕,再shutdownNow()强制关闭(采用Thread.interrupt()的方式)。再次awaitTermination()等待一段时间,这里是针对上面说的不响应Thread.interrupt()的任务。如果还没有terminated,就提示Executor没有完成关闭,还有线程在执行任务。
void shutdownAndAwaitTermination(ExecutorService pool) { pool.shutdown(); // Disable new tasks from being submitted try { // Wait a while for existing tasks to terminate if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { pool.shutdownNow(); // Cancel currently executing tasks // Wait a while for tasks to respond to being cancelled if (!pool.awaitTermination(60, TimeUnit.SECONDS)) System.err.println("Pool did not terminate"); } } catch (InterruptedException ie) { // (Re-)Cancel if current thread also interrupted pool.shutdownNow(); // Preserve interrupt status Thread.currentThread().interrupt(); } }
除了关闭Executor和检查Executor状态的方法外,ExecutorService还定义了一系列的submit()和invoke()来支持任务异步执行和批量执行。
submit()方法支持Callable接口和普通的Runnable接口,它的目的是返回一个Future对象来支持任务的异步执行。调用者可以通过Future对象来检查任务的执行状态。后面会具体介绍Future相关的内容。
invokeAll()和invokeAny()提供了批量执行任务的接口。
相关文章推荐
- springMVC教程-快速入手-深入分析
- [转] C#与Java的比较
- Java学习线路
- 使用Spring实现属性文件给常量赋值
- java int与integer的区别
- Java内部类总结
- Java 中文乱码学习 与Spring @ResponseBody中的乱码 - Spring @ResponseBody中的乱码
- 技术文章积累及MyEclipse项目布置心得
- JNI调用——处理Java的数组
- 详细解析Java中抽象类和接口的区别
- java 关于日期的记录
- Java之I/O(1-InputStream类及其子类)
- 使用spring+maven时配置文件中的特殊字符处理
- Java语言的面向对象
- Java学习-017-EXCEL 文件读取实例源代码
- Eclipse导出可运行的jar包,作为工具发布webService接口
- 二次设置布局管理器的结果
- 设置Myeclipse字体以及主题
- Springmvc提交日期类型参数
- RSA加密解密及数字签名Java实现