Java文档:并发库(一)【接口:Exectuor接口族】

来源:互联网 发布:系统之网络神豪 编辑:程序博客网 时间:2024/04/29 06:51

从Java1.5到1.6到1.7到1.8,Java的并发能力一直在提升,库也越来越多,有新有旧。
找了很多并发的博客,用到的只是库中的一部分,所以想自己把文档中的内容做一个翻译,加深记忆。
原文档:http://tool.oschina.net/apidocs/apidoc?api=jdk_7u4
库:java.util.concurrent
(1)interface 部分
该库中有如下interface:
A:BlockingDeque, BlockingQueue, TransferQueue
B:Callable, ThreadFactory, ConcurrentMap, Delayed, 
C:Executor, ExecutorService, RejectExecutionHandler, ScheduledExecutorService, CompletionService, 
D:ForkJoinPool.ForkJoinWorkerThreadFactory, ForkJoinPool.ManageBlocker, 
E:Future, RunnableFuture, RunnableScheduledFuture, ScheudledFutrue, 
其中比较关键的,应该是C E类接口
分别解释(根据文档翻译整理):

C)Executor:

子接口:ExecutorService ScheduledExecutorService

实现类:AbstractExecutorService, ForkJoinPool, ScheduledThreadPoolExecutor, ThreadPoolExecutor
该接口的实例是一个执行(executes)提交的Runnable任务(task)的对象。这个接口提供了一种方法,可以把
task submission从每一个任务如何运行的细节中解耦,包括线程使用的细节,时序,等等。一个Executor实例通常用于替代显式创建线程。
比如,原来运行单个线程的方式是: new Thread(new(RunnableTask())).start(),而现在你可以用下面的方式:
Executor executor = anExecutor;
 executor.execute(new RunnableTask1());
 executor.execute(new RunnableTask2());
然而,Executor接口并不严格要求执行的操作是异步的。在最简单的情形下,一个executor对象可以在调用者线程立即执行提交的任务(submitted task):
class DirectExecutor implements Executor {
     public void execute(Runnable r) {//runnable对象就是submitted task
         r.run();//调用run立即执行任务
     }
 }
在大部分典型应用中,任务在除调用者线程外的其他线程中执行。下面这个executor实现为每一个任务产生一个新线程:
 class ThreadPerTaskExecutor implements Executor {
     public void execute(Runnable r) {
         new Thread(r).start();
     }
 }
如果任务的执行是有序,有的Executor强加某种有序的限制。下面这个executor实现把任务顺序提供给另一个executor实例,比如一个复合的executor实例:
 class SerialExecutor implements Executor {
   final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
   final Executor executor;
   Runnable active;


   SerialExecutor(Executor executor) {
     this.executor = executor;
   }


   public synchronized void execute(final Runnable r) {
     tasks.offer(new Runnable() {
       public void run() {
         try {
           r.run();
         } finally {
           scheduleNext();
         }
       }
     });
     if (active == null) {
       scheduleNext();
     }
   }


   protected synchronized void scheduleNext() {
     if ((active = tasks.poll()) != null) {
       executor.execute(active);
     }
   }
 }
在当前包里实现的executor实现接口是ExecutorService,它是一个扩展的接口。ThreadPoolExecutor类提供了一个扩展的线程池实现。Executors类为生成这些Executor实例提供了便捷的工厂方法。
内存一致性要求:把一个runnable对象提交一个Executor实例的动作必须在调用execute之前(可能在另一个线程中)。
主要的方法:void execute(Runnable command)  作用:在未来的某一时刻执行给定的command。command可以在一个新线程、线程池或者调用线程中执行,这由Executor的实现类决定。


接口:ExecutorService  

子接口:ScheduledExecutorService

实现类:AbstractExecutorService, ForkJoinPool, ScheduledThreadPoolExecutor, ThreadPoolExecutor
提供方法管理termination,提供方法生成一个Future对象来跟踪一个或多个异步任务(asynchronous tasks)的进度。
ExecutorService可以被关闭(shut down),这将导致其拒绝执行新的任务。有两种不同的关闭方法。shutdown()方法允许已提交的任务在服务终止前获得执行,而shutdownNow()方法会阻止等待中的任务执行
并且尝试停止当前正在执行的任务。一旦termination,executor实例将不在有任务被执行,也没有任务等待执行,也没有新任务可以提交。一个未使用的ExecutorService实例允许关闭并回收其资源。
submit方法继承了基类方法Executor.execute(java.lang.Runnable) 的功能by creating,并且返回一个Future实例,该实例可用于取消执行和/或等待执行过程完成。方法invokeAny和invokeAll
执行大部分通用的有用的松散执行过程,执行一组任务(tasks)并等待至少一个、或者全部任务执行完成。(ExecutorCompletionService类……)
本包中的Executors类提供了生成executor services实例的工厂方法。
示例:
class NetworkService implements Runnable {
   private final ServerSocket serverSocket;
   private final ExecutorService pool;


   public NetworkService(int port, int poolSize)
       throws IOException {
     serverSocket = new ServerSocket(port);
     pool = Executors.newFixedThreadPool(poolSize);
   }


   public void run() { // run the service
     try {
       for (;;) {
         pool.execute(new Handler(serverSocket.accept()));
       }
     } catch (IOException ex) {
       pool.shutdown();
     }
   }
 }


 class Handler implements Runnable {
   private final Socket socket;
   Handler(Socket socket) { this.socket = socket; }
   public void run() {
     // read and service request on socket
   }
 }
 下面这个示例演示了两种关闭ExecutorServices的方法:
 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();
   }
 }
类成员方法:
void shutdown():有序关闭正在执行的任务,并不再接受新的任务。准备关闭服务的时候,该方法不会有其他作用。该方法不会等待已执行的任务执行完毕,可以用waitTermination等待。
List<Runnable> shutdownNow():尝试停止所有执行中的任务,停止等待中的任务,并返回等待中的任务列表。该方法不会等待执行中的任务执行完毕。
isTerminated():如果所有任务都关闭,则返回true。如果没有调用shutdown或者shutdownNow,则一直返回false。
boolean awaitTermination(long timeout,TimeUnit unit)throws InterruptedException:阻塞直到所有任务在shutdown请求发出后执行完,或者当前线程被中断。
<T> Future<T> submit(Callable<T> task):
<T> Future<T> submit(Runnable task,T result):
Future<?> submit(Runnable task):Future的get方法可以获得任务执行成功的返回结果。如果阻塞等待任务并立即返回结果,可以用格式:result = exec.submit(aCallable).get();
<T> List<Future<T>> invokeAll/invokeAny(Collection<? extends Callable<T>> tasks)throws InterruptedException:
<T> List<Future<T>> invokeAll/invokeAny(Collection<? extends Callable<T>> tasks,long timeout,TimeUnit unit)throws InterruptedException:执行给定的任务,返回执行成功的
任务的结果。如果发生异常,未完成的任务会中止。如果给定的集合在执行过程中被修改,则返回值是未定义的。


接口:ScheduledExecutorService
该接口可以安排任务在给定延迟后执行,或者周期性执行。schedule方法用不同的延时参数创建任务,并返回一个可以中止或者检查执行过程的任务对象(task object)。scheduleAtFixdRate
和scheduleWithFixedDelay方法创建并执行周期性任务直到被中止。命令提交使用 Executor.execute(java.lang.Runnable) 和 ExecutorService submit方法,如果传入0或者负数的延时(不是
周期)也是允许的,会被解释为请求立即执行任务。所以的schedule方法接收相对延时和周期值作为参数,不是绝对时间或者日期。不过可以把Date之类的绝对时间很简单的转换为需要的时间,比如
计划在将来一个确定的时间点date,你可以用:schedule(task, date.getTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS)(TimeUnit是concurrent包的一个类)。Executors类
提供了生成ScheduledExecutorService 实例的工厂方法。
示例:
import static java.util.concurrent.TimeUnit.*;
 class BeeperControl {
   private final ScheduledExecutorService scheduler =
     Executors.newScheduledThreadPool(1);


   public void beepForAnHour() {
     final Runnable beeper = new Runnable() {
       public void run() { System.out.println("beep"); }
     };
     final ScheduledFuture<?> beeperHandle =
       scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
     scheduler.schedule(new Runnable() {
       public void run() { beeperHandle.cancel(true); }
     }, 60 * 60, SECONDS);
   }
 }


后记:通过对这三个接口的翻译,可以看出来这个接口的主要作用是集中运行线程,比如多线程服务器,每接收到一个请求,需要开启一个线程与客户端交互(先不考虑线程池),原来的代码是调用多次new Thread(new(RunnableTask())).start(),现在可以在executor中调用一次创建线程即可,而且扩展的接口实现了任务(或子线程)的周期执行和延时执行,支持任务的过程检测,支持任务返回结果。Future作为返回结果,可以实现任务的异步执行,只要一直用Future实例检测结果,就可以判断任务是否完成,任务的

返回结果是什么,对于Callable<T>的call(),返回值是T类型,对于Runnable,调用submit(Runnable,T result),成功时从Future获得T result。异步应该是最大的用处。





















0 0
原创粉丝点击