一、Executor 接口简介
Executor接口是Executor框架的一个最基本的接口,Executor框架的大部分类都直接或间接地实现了此接口。
只有一个方法
void execute(Runnable command): 在未来某个时间执行给定的命令。该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。
Executor的几种实现原理介绍:
1、 <font color="blue">Executor 接口并没有严格地要求执行是异步的。</font>在最简单的情况下,执行程序可以在调用者的线程中立即运行已提交的任务:
1 class DirectExecutor implements Executor { 2 public void execute(Runnable r) { 3 r.run(); 4 } 5 }
2、 更常见的是,任务是在某个不是调用者线程的线程中执行的。以下执行程序将为每个任务生成一个新线程。
1class ThreadPerTaskExecutor implements Executor { 2 public void execute(Runnable r) { 3 new Thread(r).start(); 4 } 5 }
3、 许多 Executor 实现都对调度任务的方式和时间强加了某种限制。以下执行程序使任务提交与第二个执行程序保持连续,这说明了一个复合执行程序。
1 class SerialExecutor implements Executor { 2 private final Queue<Runnable> tasks = new ArrayDeque<Runnable>(); 3 private final Executor executor; 4 Runnable active; 5 6 SerialExecutor(Executor executor) { 7 this.executor = executor; 8 } 9 10 public synchronized void execute(final Runnable r) { 11 tasks.offer(new Runnable() { 12 public void run() { 13 try { 14 r.run(); 15 } finally { 16 scheduleNext(); 17 } 18 } 19 }); 20 if (active == null) { 21 scheduleNext(); 22 } 23 } 24 25 protected synchronized void scheduleNext() { 26 if ((active = tasks.poll()) != null) { 27 executor.execute(active); 28 } 29 } 30 31 }
二、ExecutorService 接口简介
ExecutorService 是一个接口,提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成Future 的方法。 ExecutorService 的实现:
- 三个实现类:
AbstractExecutorService(默认实现类) ,ScheduledThreadPoolExecutor,ThreadPoolExecutor Executors提供了此接口的几种常用实现的工厂方法。
方法摘要
1. 从Executor 接口中继承了不跟踪异步线程,没有返回的 execute 方法:
void execute(Runnable command):
在未来某个时间执行给定的命令。该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。
2. 扩展的跟踪异步线程、返回Future 接口的实现类的方法:
Future<?> submit(Runnable task): 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在成功 完成时将会返回 null。
**<T> Future<T> submit(Runnable task,T result): ** 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在成功完成时将会返回给定的结果。
<T> Future<T> submit(Callable<T> task): 提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。<font color="blue">该 Future 的 get 方法在成功完成时将会返回该任务的结果。如果想立即<font color="red">阻塞任务的等待</font>,则可以使用 result = exec.submit(aCallable).get(); 形式的构造</font>
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException: 执行给定的任务,当所有任务完成时,返回保持任务状态和结果的 Future 列表。返回列表的所有元素的 Future.isDone() 为 true。注意,可以正常地或通过抛出异常来终止已完成 任务。如果正在进行此操作时修改了给定的 collection,则此方法的结果是不确定的。
<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: 与 invokeAll的区别是,<font color="red">任务列表里只要有一个任务完成了,就立即返回。而且一旦正常或异常返回后,则取消尚未完成的任务。</font>
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,long timeout,TimeUnit unit) throws InterruptedException: 超时等待,同上。
boolean awaitTermination(long timeout,TimeUnit unit) throws InterruptedException: 一直等待,直到所有任务完成。请求关闭、发生超时或者当前线程中断,无论哪一个首先发生之后,都将导致阻塞,直到所有任务完成执行,或者超时时间的到来<font color="red">如果此执行程序终止,则返回 true;如果终止前超时期满,则返回 false </font>
3. 管理生命周期
void shutdown(): 启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用。 List<Runnable> shutdownNow(): 试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。 无法保证能够停止正在处理的活动执行任务,但是会尽力尝试。例如,<font color="blue">在 ThreadPoolExecutor 中,通过 Thread.interrupt() 来取消典型的实现,所以如果任务无法响应中断,则永远无法终止。</font> boolean isShutdown(): 如果此执行程序已关闭,则返回 true。 boolean isTerminated(): 如果关闭后所有任务都已完成,则返回 true。注意,除非首先调用 shutdown 或 shutdownNow,否则 isTerminated 永不为 true。
用法示例
下面给出了一个网络服务的简单结构,这里线程池中的线程作为传入的请求。它使用了预先配置的 Executors.newFixedThreadPool(int) 工厂方法:
<br/>1class NetworkService implements Runnable { 2 private final ServerSocket serverSocket; 3 private final ExecutorService pool; 4 5 public NetworkService(int port, int poolSize) 6 throws IOException { 7 serverSocket = new ServerSocket(port); 8 pool = Executors.newFixedThreadPool(poolSize); 9 } 10 11 public void run() { // run the service 12 try { 13 for (;;) { 14 pool.execute(new Handler(serverSocket.accept())); 15 } 16 } catch (IOException ex) { 17 pool.shutdown(); 18 } 19 } 20 } 21 22 class Handler implements Runnable { 23 private final Socket socket; 24 Handler(Socket socket) { this.socket = socket; } 25 public void run() { 26 // read and service request on socket 27 } 28 } 29
下列方法分两个阶段关闭 ExecutorService。第一阶段调用 shutdown 拒绝传入任务,然后调用 shutdownNow(如有必要)取消所有遗留的任务:
1 void shutdownAndAwaitTermination(ExecutorService pool) { 2 pool.shutdown(); // Disable new tasks from being submitted 3 try { 4 // Wait a while for existing tasks to terminate 5 if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { 6 pool.shutdownNow(); // Cancel currently executing tasks 7 // Wait a while for tasks to respond to being cancelled 8 if (!pool.awaitTermination(60, TimeUnit.SECONDS)) 9 System.err.println("Pool did not terminate"); 10 } 11 } catch (InterruptedException ie) { 12 // (Re-)Cancel if current thread also interrupted 13 pool.shutdownNow(); 14 // Preserve interrupt status 15 Thread.currentThread().interrupt(); 16 } 17 }
参考文献
- 《java并发编程的艺术》