Java Thread&Concurrency(12): 深入理解AbstractExecutorService及其实现原理
2014-07-22 12:48
901 查看
AbstractExecutorService主要是作为ExecutorService的一个抽象实现,本身是一个抽象类。最后的执行会依托于execute方法。
它提供了类似如下的方法:
可以通过对任务单元的封装,和Future接口的配合,从而返回一个可以获得任务结果的实现。
本文我们主要来看看对于任务集合的几个操作:invokeAll和invokeAny。
invokeAll:
首先取得限时参数nanos,构造集合futures。
为所有任务都构造任务单元并且加入futures,然后提交每个任务,假如超时则返回任务集合futures。
对于所有任务,依次阻塞直到任务完成,假如超过时限则直接返回。
最后假如不是所有任务都完成,则尝试取消所有任务。
再来看invokeAny:
与之前一样构造集合futures,时间参数nanos。
这里的采用了另一个带有“完成”功能的执行服务ecs(ExecutorCompletionService)来封装当前执行服务。
对任务集合tasks遍历,采用"一提交/一轮询"的方式来执行,假如有某个任务有了结果,那么就直接返回结果。有限时和立即两个轮询版本(poll)。
假如所有任务都在执行过程中抛出异常,则这里最终会抛出ExecutionException异常,如果超时则抛出TimeoutException异常。
最后取消所有未完成的任务。
这种方式巧妙的实现了只需要执行并得到一个任务的结果即可。
它提供了类似如下的方法:
public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerException(); RunnableFuture<Void> ftask = newTaskFor(task, null); execute(ftask); return ftask; }
public <T> Future<T> submit(Callable<T> task) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task); execute(ftask); return ftask; }
可以通过对任务单元的封装,和Future接口的配合,从而返回一个可以获得任务结果的实现。
本文我们主要来看看对于任务集合的几个操作:invokeAll和invokeAny。
invokeAll:
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException { if (tasks == null) throw new NullPointerException(); long nanos = unit.toNanos(timeout); ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size()); boolean done = false; try { for (Callable<T> t : tasks) futures.add(newTaskFor(t)); final long deadline = System.nanoTime() + nanos; final int size = futures.size(); // Interleave time checks and calls to execute in case // executor doesn't have any/much parallelism. for (int i = 0; i < size; i++) { execute((Runnable)futures.get(i)); nanos = deadline - System.nanoTime(); if (nanos <= 0L) return futures; } for (int i = 0; i < size; i++) { Future<T> f = futures.get(i); if (!f.isDone()) { if (nanos <= 0L) return futures; try { f.get(nanos, TimeUnit.NANOSECONDS); } catch (CancellationException ignore) { } catch (ExecutionException ignore) { } catch (TimeoutException toe) { return futures; } nanos = deadline - System.nanoTime(); } } done = true; return futures; } finally { if (!done) for (int i = 0, size = futures.size(); i < size; i++) futures.get(i).cancel(true); } }
首先取得限时参数nanos,构造集合futures。
为所有任务都构造任务单元并且加入futures,然后提交每个任务,假如超时则返回任务集合futures。
对于所有任务,依次阻塞直到任务完成,假如超过时限则直接返回。
最后假如不是所有任务都完成,则尝试取消所有任务。
再来看invokeAny:
private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks, boolean timed, long nanos) throws InterruptedException, ExecutionException, TimeoutException { if (tasks == null) throw new NullPointerException(); int ntasks = tasks.size(); if (ntasks == 0) throw new IllegalArgumentException(); ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks); ExecutorCompletionService<T> ecs = new ExecutorCompletionService<T>(this); // For efficiency, especially in executors with limited // parallelism, check to see if previously submitted tasks are // done before submitting more of them. This interleaving // plus the exception mechanics account for messiness of main // loop. try { // Record exceptions so that if we fail to obtain any // result, we can throw the last exception we got. ExecutionException ee = null; final long deadline = timed ? System.nanoTime() + nanos : 0L; Iterator<? extends Callable<T>> it = tasks.iterator(); // Start one task for sure; the rest incrementally futures.add(ecs.submit(it.next())); --ntasks; int active = 1; for (;;) { Future<T> f = ecs.poll(); if (f == null) { if (ntasks > 0) { --ntasks; futures.add(ecs.submit(it.next())); ++active; } else if (active == 0) break; else if (timed) { f = ecs.poll(nanos, TimeUnit.NANOSECONDS); if (f == null) throw new TimeoutException(); nanos = deadline - System.nanoTime(); } else f = ecs.take(); } if (f != null) { --active; try { return f.get(); } catch (ExecutionException eex) { ee = eex; } catch (RuntimeException rex) { ee = new ExecutionException(rex); } } } if (ee == null) ee = new ExecutionException(); throw ee; } finally { for (int i = 0, size = futures.size(); i < size; i++) futures.get(i).cancel(true); } }
与之前一样构造集合futures,时间参数nanos。
这里的采用了另一个带有“完成”功能的执行服务ecs(ExecutorCompletionService)来封装当前执行服务。
对任务集合tasks遍历,采用"一提交/一轮询"的方式来执行,假如有某个任务有了结果,那么就直接返回结果。有限时和立即两个轮询版本(poll)。
假如所有任务都在执行过程中抛出异常,则这里最终会抛出ExecutionException异常,如果超时则抛出TimeoutException异常。
最后取消所有未完成的任务。
这种方式巧妙的实现了只需要执行并得到一个任务的结果即可。
相关文章推荐
- Java Thread&Concurrency(10): 深入理解ThreadLocal及其实现原理
- Java Thread&Concurrency(16): 深入理解ArrayBlockingQueue及其实现原理
- Java Thread&Concurrency(11): 深入理解ThreadPoolExecutor及其实现原理
- Java Thread&Concurrency(15): 深入理解ScheduledThreadPoolExecutor及其实现原理
- Java Thread&Concurrency(9): 深入理解StampedLock及其实现原理
- Java Thread&Concurrency(14): 深入理解条件队列(Condition)及其实现原理
- Java Thread&Concurrency(13): 深入理解ConcurrentLinkedQueue及其实现原理
- Java Thread&Concurrency(5): 深入理解Phaser实现原理
- Java Thread&Concurrency(4): 深入理解Exchanger实现原理
- Java Thread&Concurrency(8): 深入理解CompletionService接口及其实现
- Java Thread&Concurrency(2): 深入理解ConcurrentSkipListMap实现原理
- Java Thread&Concurrency(7): 深入理解Callable/Future(FutureTask)接口及其实现
- Java Thread&Concurrency(3): 深入理解SynchronousQueue实现原理
- Java Thread&Concurrency(1): 深入理解Fork-Join并发执行框架
- 深入学习理解java:CompletionService解决ExecutorService的submit方法的缺点
- 【深入理解java集合系列】LinkedHashMap实现原理
- 深入理解Java中的HashMap的实现原理
- Java 并发编程深入学习——线程池及其实现原理
- 【深入理解java集合系列】HashSet实现原理
- 深入Java集合学习系列:ArrayBlockingQueue及其实现原理