線程池相關
源碼:
package java.util.concurrent;
import java.util.*;
public abstract class AbstractExecutorService implements ExecutorService {
/**
* 爲給定可運行任務和默認值返回一個RunnableFuture
* 參數:
* runnable - 將被包裝的可運行任務
* value - 用於所返回的將來任務的默認值
* 返回:
* 一個 RunnableFuture,在運行的時候,它將運行底層可運行任務,作爲Future任務,它將生成給定值作爲其結果,併爲底層任務提供取消操作。
*/
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
/**
* 爲給定可調用任務返回一個RunnableFuture。
* 參數:
* callable - 將包裝的可調用任務
* 返回:
* 一個RunnableFuture,在運行的時候,它將調用底層可調用任務,作爲Future任務,它將生成可調用的結果作爲其結果,併爲底層任務提供取消操作。
*/
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
/**
* 提交一個Runnable任務用於執行,並返回一個表示該任務的Future。
* 該Future的get方法在成功完成時將會返回null
*
* 方法指定者:接口 ExecutorService 中的 submit
* 參數:task - 要提交的任務
* 返回:表示任務等待完成的 Future
*/
public Future<?> submit(Runnable task) {
if (task == null)//校驗參數
throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);//創建一個RunnableFuture對象
execute(ftask);//調用繼承至ExecutorService接口的execute方法
return ftask;//返回等待任務完成的Future
}
/**
* 提交一個Runnable任務用於執行,並返回一個表示該任務的Future。
* 該Future的get方法在成功完成時將會返回給定的結果。
*
* 方法指定者:接口 ExecutorService 中的 submit
* 參數:task - 要提交的任務
* 返回:表示任務等待完成的 Future
*/
public <T> Future<T> submit(Runnable task, T result) {
if (task == null)//校驗參數
throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);//創建一個RunnableFuture對象
execute(ftask);//調用繼承至ExecutorService接口的execute方法
return ftask;//返回等待任務完成的Future
}
/**
* 提交一個返回值的任務用於執行,返回一個表示任務的未決結果的Future。
* 該Future的get方法在成功完成時將會返回該任務的結果。
*
* 方法指定者:接口 ExecutorService 中的 submit
* 參數:task - 要提交的任務
* 返回:表示任務等待完成的 Future
*/
public <T> Future<T> submit(Callable<T> task) {
if (task == null)//校驗參數
throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);//創建一個RunnableFuture對象
execute(ftask);//調用繼承至ExecutorService接口的execute方法
return ftask;//返回等待任務完成的Future
}
/**
* 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);
//爲了提高效率:檢查先前提交的任務是否在提交更多的任務之前完成。
try {
//記錄異常,如果我們不能獲得任何結果,我們可以拋出我們得到的最後一個異常。
ExecutionException ee = null;
final long deadline = timed ? System.nanoTime() + nanos : 0L;
Iterator<? extends Callable<T>> it = tasks.iterator();
//先開始一個任務; 其餘的是漸進式的
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);
}
}
/**
* 執行給定的任務,如果某個任務已成功完成(也就是未拋出異常),則返回其結果。
* 一旦正常或異常返回後,則取消尚未完成的任務。
* 如果此操作正在進行時修改了給定的collection,則此方法的結果是不確定的。
*
* 方法指定者:接口ExecutorService中的invokeAny
* 參數:tasks - 任務 collection
* 返回:某個任務返回的結果
* 拋出:
* InterruptedException - 如果等待時發生中斷
* ExecutionException - 如果沒有任務成功完成
*/
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException {
try {
return doInvokeAny(tasks, false, 0);//執行上述的私有方法
} catch (TimeoutException cannotHappen) {
assert false;
return null;
}
}
/**
* 執行給定的任務,如果在給定的超時期滿前某個任務已成功完成(也就是未拋出異常),則返回其結果。
* 一旦正常或異常返回後,則取消尚未完成的任務。
* 如果此操作正在進行時修改了給定的collection,則此方法的結果是不確定的。
*
* 方法指定者:接口ExecutorService中的invokeAny
* 參數:
* tasks - 任務 collection
* timeout - 最長等待時間
* unit - timeout 參數的時間單位
* 返回:某個任務返回的結果
* 拋出:
* InterruptedException - 如果等待時發生中斷
* ExecutionException - 如果沒有任務成功完成
* TimeoutException - 如果在所有任務成功完成之前給定的超時期滿
*/
public <T> T invokeAny(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return doInvokeAny(tasks, true, unit.toNanos(timeout));//執行上述的私有方法
}
/**
* 執行給定的任務,當所有任務完成時,返回保持任務狀態和結果的Future列表。
* 返回列表的所有元素的 Future.isDone()爲true。注意,可以正常地或通過拋出異常來終止已完成任務。
* 如果正在進行此操作時修改了給定的collection,則此方法的結果是不確定的。
*
* 方法指定者:接口ExecutorService中的invokeAll
* 參數:
* tasks - 任務 collection
* 返回:
* 表示任務的 Future 列表,列表順序與給定任務列表的迭代器所生成的順序相同,每個任務都已完成。
* 拋出:
* InterruptedException - 如果等待時發生中斷,在這種情況下取消尚未完成的任務。
*/
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> t : tasks) {
RunnableFuture<T> f = newTaskFor(t);
futures.add(f);
execute(f);
}
for (int i = 0, size = futures.size(); i < size; i++) {
Future<T> f = futures.get(i);
if (!f.isDone()) {
try {
f.get();
} catch (CancellationException ignore) {
} catch (ExecutionException ignore) {
}
}
}
done = true;
return futures;
} finally {
if (!done)
for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);
}
}
/**
* 執行給定的任務,當所有任務完成或超時期滿時(無論哪個首先發生),返回保持任務狀態和結果的Future列表。
* 返回列表的所有元素的Future.isDone()爲 true。一旦返回後,即取消尚未完成的任務。
* 注意,可以正常地或通過拋出異常來終止 已完成 任務。如果此操作正在進行時修改了給定的collection,則此方法的結果是不確定的。
* 指定者:接口ExecutorService中的invokeAll
* 參數:
* tasks - 任務 collection
* timeout - 最長等待時間
* unit - timeout 參數的時間單位
* 返回:
* 表示任務的 Future 列表,列表順序與給定任務列表的迭代器所生成的順序相同。
* 如果操作未超時,則已完成所有任務。
* 如果確實超時了,則某些任務尚未完成。
* 拋出:
* InterruptedException - 如果等待時發生中斷,在這種情況下取消尚未完成的任務
*/
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();
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);
}
}
}
類 AbstractExecutorService
已實現的接口:
已知子類:
此類使用 newTaskFor 返回的 RunnableFuture
實現 submit、invokeAny 和 invokeAll 方法,默認情況下,RunnableFuture
是此包中提供的 FutureTask
類。例如,submit(Runnable) 的實現創建了一個關聯 RunnableFuture 類,該類將被執行並返回。子類可以重寫 newTaskFor 方法,以返回 FutureTask 之外的 RunnableFuture 實現。
擴展示例。以下是一個類的簡要介紹,該類定製 ThreadPoolExecutor
使用 CustomTask 類替代默認 FutureTask:
public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
static class CustomTask<V> implements RunnableFuture<V> {...}
protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) {
return new CustomTask<V>(c);
}
protected <V> RunnableFuture<V> newTaskFor(Runnable r, V v) {
return new CustomTask<V>(r, v);
}
// ... add constructors, etc.
}
方法摘要
|
invokeAll(Collection<? extends Callable<T>> tasks) 執行給定的任務,當所有任務完成時,返回保持任務狀態和結果的 Future 列表。 |
|
|
invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) 執行給定的任務,當所有任務完成或超時期滿時(無論哪個首先發生),返回保持任務狀態和結果的 Future 列表。 |
|
|
invokeAny(Collection<? extends Callable<T>> tasks) 執行給定的任務,如果某個任務已成功完成(也就是未拋出異常),則返回其結果。 |
|
|
invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) 執行給定的任務,如果在給定的超時期滿前某個任務已成功完成(也就是未拋出異常),則返回其結果。 |
|
protected
|
newTaskFor(Callable<T> callable) 爲給定可調用任務返回一個 RunnableFuture。 |
|
protected
|
newTaskFor(Runnable runnable, T value) 爲給定可運行任務和默認值返回一個 RunnableFuture。 |
|
|
submit(Callable<T> task) 提交一個返回值的任務用於執行,返回一個表示任務的未決結果的 Future。 |
|
Future<?> |
submit(Runnable task) 提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。 |
|
|
submit(Runnable task, T result) 提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。 |
從類 java.lang.Object 繼承的方法
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
從接口 java.util.concurrent.ExecutorService 繼承的方法
awaitTermination, isShutdown, isTerminated, shutdown, shutdownNow
從接口 java.util.concurrent.Executor 繼承的方法
newTaskFor
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable,T value)
爲給定可運行任務和默認值返回一個 RunnableFuture。
參數:
runnable
- 將被包裝的可運行任務
value
- 用於所返回的將來任務的默認值
返回:
一個 RunnableFuture,在運行的時候,它將運行底層可運行任務,作爲 Future 任務,它將生成給定值作爲其結果,併爲底層任務提供取消操作。
newTaskFor
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable)
爲給定可調用任務返回一個 RunnableFuture。
參數:
callable
- 將包裝的可調用任務
返回:
一個 RunnableFuture,在運行的時候,它將調用底層可調用任務,作爲 Future 任務,它將生成可調用的結果作爲其結果,併爲底層任務提供取消操作。
submit
public Future<?> submit(Runnable task)
從接口 ExecutorService
複製的描述
提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。該 Future 的 get 方法在 成功 完成時將會返回 null。
指定者:
接口 ExecutorService
中的 submit
參數:
task
- 要提交的任務
返回:
表示任務等待完成的 Future
submit
public <T> Future<T> submit(Runnable task, T result)
從接口 ExecutorService
複製的描述
提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。該 Future 的 get 方法在成功完成時將會返回給定的結果。
指定者:
接口 ExecutorService
中的 submit
參數:
task
- 要提交的任務
result
- 返回的結果
返回:
表示任務等待完成的 Future
submit
public <T> Future<T> submit(Callable<T> task)
從接口 ExecutorService
複製的描述
提交一個返回值的任務用於執行,返回一個表示任務的未決結果的 Future。該 Future 的 get 方法在成功完成時將會返回該任務的結果。
如果想立即阻塞任務的等待,則可以使用 result = exec.submit(aCallable).get(); 形式的構造。
注:Executors
類包括了一組方法,可以轉換某些其他常見的類似於閉包的對象,例如,將 PrivilegedAction
轉換爲 Callable
形式,這樣就可以提交它們了。
指定者:
接口 ExecutorService
中的 submit
參數:
task
- 要提交的任務
返回:
表示任務等待完成的 Future
invokeAny
public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException
從接口 ExecutorService
複製的描述
執行給定的任務,如果某個任務已成功完成(也就是未拋出異常),則返回其結果。一旦正常或異常返回後,則取消尚未完成的任務。如果此操作正在進行時修改了給定的 collection,則此方法的結果是不確定的。
指定者:
接口 ExecutorService
中的 invokeAny
參數:
tasks
- 任務 collection
返回:
某個任務返回的結果
拋出:
InterruptedException
- 如果等待時發生中斷
ExecutionException
- 如果沒有任務成功完成
invokeAny
public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
從接口 ExecutorService
複製的描述
執行給定的任務,如果在給定的超時期滿前某個任務已成功完成(也就是未拋出異常),則返回其結果。一旦正常或異常返回後,則取消尚未完成的任務。如果此操作正在進行時修改了給定的 collection,則此方法的結果是不確定的。
指定者:
接口 ExecutorService
中的 invokeAny
參數:
tasks
- 任務 collection
timeout
- 最長等待時間
unit
- timeout 參數的時間單位
返回:
某個任務返回的結果
拋出:
InterruptedException
- 如果等待時發生中斷
ExecutionException
- 如果沒有任務成功完成
TimeoutException
- 如果在所有任務成功完成之前給定的超時期滿
invokeAll
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException
從接口 ExecutorService
複製的描述
執行給定的任務,當所有任務完成時,返回保持任務狀態和結果的 Future 列表。返回列表的所有元素的 Future.isDone()
爲 true。注意,可以正常地或通過拋出異常來終止 已完成 任務。如果正在進行此操作時修改了給定的 collection,則此方法的結果是不確定的。
指定者:
接口 ExecutorService
中的 invokeAll
參數:
tasks
- 任務 collection
返回:
表示任務的 Future 列表,列表順序與給定任務列表的迭代器所生成的順序相同,每個任務都已完成。
拋出:
InterruptedException
- 如果等待時發生中斷,在這種情況下取消尚未完成的任務。
invokeAll
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException
從接口 ExecutorService
複製的描述
執行給定的任務,當所有任務完成或超時期滿時(無論哪個首先發生),返回保持任務狀態和結果的 Future 列表。返回列表的所有元素的 Future.isDone()
爲 true。一旦返回後,即取消尚未完成的任務。注意,可以正常地或通過拋出異常來終止 已完成 任務。如果此操作正在進行時修改了給定的 collection,則此方法的結果是不確定的。
指定者:
接口 ExecutorService
中的 invokeAll
參數:
tasks
- 任務 collection
timeout
- 最長等待時間
unit
- timeout 參數的時間單位
返回:
表示任務的 Future 列表,列表順序與給定任務列表的迭代器所生成的順序相同。如果操作未超時,則已完成所有任務。如果確實超時了,則某些任務尚未完成。
拋出:
InterruptedException
- 如果等待時發生中斷,在這種情況下取消尚未完成的任務
實現原理
AbstractExecutorService對ExecutorService的執行任務類型的方法提供了一個默認實現。這些方法包括submit,invokeAny和InvokeAll。
注意的是來自Executor接口的execute方法是未被實現,execute方法是整個體系的核心,所有的任務都是在這個方法裏被真正執行的,因此該方法的不同實現會帶來不同的執行策略。
這個在分析ThreadPoolExecutor和ScheduledThreadPoolExecutor就能看出來。
首先來看submit方法,它的基本邏輯是這樣的:
1. 生成一個任務類型和Future接口的包裝接口RunnableFuture的對象
2. 執行任務
3. 返回future。
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;
}
因爲submit支持Callable和Runnable兩種類型的任務,因此newTaskFor方法有兩個重載方法:
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
Callable和Runnable的區別在於前者帶返回值,也就是說Callable=Runnable+返回值。
因此java中提供了一種adapter,把Runnable+返回值轉換成Callable類型。這點可以在newTaskFor中的FutureTask類型的構造函數的代碼中看到:
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
sync = new Sync(callable);
}
public FutureTask(Runnable runnable, V result) {
sync = new Sync(Executors.callable(runnable, result));
}
以下是Executors.callable方法的代碼:
public static <T> Callable<T> callable(Runnable task, T result) {
if (task == null)
throw new NullPointerException();
return new RunnableAdapter<T>(task, result);
}
那麼RunnableAdapter的代碼就很好理解了,它是一個Callable的實現,call方法的實現就是執行Runnable的run方法,然後返回那個value。
static final class RunnableAdapter<T> implements Callable<T> {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result;
}
}
接下來先說說較爲簡單的invokeAll:
1. 爲每個task調用newTaskFor方法生成得到一個既是Task也是Future的包裝類對象的List
2. 循環調用execute執行每個任務
3. 再次循環調用每個Future的get方法等待每個task執行完成
4. 最後返回Future的list。
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException {
if (tasks == null || unit == null)
throw new NullPointerException();
long nanos = unit.toNanos(timeout);
List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
// 爲每個task生成包裝對象
for (Callable<T> t : tasks)
futures.add(newTaskFor(t));
long lastTime = System.nanoTime();
// 循環調用execute執行每個方法
// 這裏因爲設置了超時時間,所以每次執行完成後
// 檢查是否超時,超時了就直接返回future集合
Iterator<Future<T>> it = futures.iterator();
while (it.hasNext()) {
execute((Runnable)(it.next()));
long now = System.nanoTime();
nanos -= now - lastTime;
lastTime = now;
if (nanos <= 0)
return futures;
}
// 等待每個任務執行完成
for (Future<T> f : futures) {
if (!f.isDone()) {
if (nanos <= 0)
return futures;
try {
f.get(nanos, TimeUnit.NANOSECONDS);
} catch (CancellationException ignore) {
} catch (ExecutionException ignore) {
} catch (TimeoutException toe) {
return futures;
}
long now = System.nanoTime();
nanos -= now - lastTime;
lastTime = now;
}
}
done = true;
return futures;
} finally {
if (!done)
for (Future<T> f : futures)
f.cancel(true);
}
}
最後說說invokeAny,它的難點在於只要一個任務執行成功就要返回,並且會取消其他任務,也就是說重點在於找到第一個執行成功的任務。
因爲兩個invokeAny方法都是調用doInvokeAny方法,下面是doInvokeAny的代碼分析:
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();
List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
// ExecutorCompletionService負責執行任務,後面調用用poll返回第一個執行結果
ExecutorCompletionService<T> ecs = new ExecutorCompletionService<T>(this);
// 這裏出於效率的考慮,每次提交一個任務之後,就檢查一下有沒有執行完成的任務
try {
ExecutionException ee = null;
long lastTime = timed ? System.nanoTime() : 0;
Iterator<? extends Callable<T>> it = tasks.iterator();
// 先提交一個任務
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();
// 這裏的更新不可少,因爲這個Future可能是執行失敗的情況,那麼還需要再次等待下一個結果,超時的設置還是需要用到。
long now = System.nanoTime();
nanos -= now - lastTime;
lastTime = now;
}
// 沒有設置超時,並且所有任務都被提交了,則一直等到第一個執行結果出來
else
f = ecs.take();
}
// 有返回結果了,嘗試從future中獲取結果,如果失敗了,那麼需要接着等待下一個執行結果
if (f != null) {
--active;
try {
return f.get();
} catch (ExecutionException eex) {
ee = eex;
} catch (RuntimeException rex) {
ee = new ExecutionException(rex);
}
}
}
// ExecutorCompletionService執行時發生錯誤返回了全是null的future
if (ee == null)
ee = new ExecutionException();
throw ee;
} finally {
// 嘗試取消所有的任務(對於已經完成的任務沒有影響)
for (Future<T> f : futures)
f.cancel(true);
}
}
當所有的任務被提交後,任務執行返回的Future會被依次添加到一個BlockingQueue中,然後找到第一個執行成功任務的方法就是從BlockingQueue取出第一個元素,這個就是doInvokeAny方法用到的ExecutorCompletionService的基本原理。
package java.util.concurrent;
public class ExecutorCompletionService<V> implements CompletionService<V> {
private final Executor executor;
private final AbstractExecutorService aes;
private final BlockingQueue<Future<V>> completionQueue;
//內部類
private class QueueingFuture extends FutureTask<Void> {
QueueingFuture(RunnableFuture<V> task) {
super(task, null);
this.task = task;
}
protected void done() { completionQueue.add(task); }
private final Future<V> task;
}
//爲Callable對象實例返回一個RunnableFuture
private RunnableFuture<V> newTaskFor(Callable<V> task) {
if (aes == null)
return new FutureTask<V>(task);
else
return aes.newTaskFor(task);
}
//爲Runnable對象實例返回一個RunnableFuture
private RunnableFuture<V> newTaskFor(Runnable task, V result) {
if (aes == null)
return new FutureTask<V>(task, result);
else
return aes.newTaskFor(task, result);
}
//構造器
public ExecutorCompletionService(Executor executor) {
if (executor == null)
throw new NullPointerException();
this.executor = executor;
this.aes = (executor instanceof AbstractExecutorService) ?
(AbstractExecutorService) executor : null;
this.completionQueue = new LinkedBlockingQueue<Future<V>>();
}
//構造器
public ExecutorCompletionService(Executor executor,
BlockingQueue<Future<V>> completionQueue) {
if (executor == null || completionQueue == null)
throw new NullPointerException();
this.executor = executor;
this.aes = (executor instanceof AbstractExecutorService) ?
(AbstractExecutorService) executor : null;
this.completionQueue = completionQueue;
}
//執行隊列中的節點線程方法
public Future<V> submit(Callable<V> task) {
if (task == null)//檢查參數
throw new NullPointerException();
RunnableFuture<V> f = newTaskFor(task);//創建一個RunnableFuture對象實例
executor.execute(new QueueingFuture(f));//執行隊列中的一個節點
return f;
}
//執行隊列中的線程方法
public Future<V> submit(Runnable task, V result) {
if (task == null)//檢查參數
throw new NullPointerException();
RunnableFuture<V> f = newTaskFor(task, result);//創建一個RunnableFuture對象實例
executor.execute(new QueueingFuture(f));//執行隊列中的一個節點
return f;
}
//獲取並移除此隊列的頭部,在元素變得可用之前一直等待
public Future<V> take() throws InterruptedException {
return completionQueue.take();
}
//將指定元素插入此隊列中,將等待可用的空間(如果有必要)
public Future<V> poll() {
return completionQueue.poll();
}
//獲取並移除此隊列的頭部,在指定的等待時間前等待可用的元素(如果有必要)
public Future<V> poll(long timeout, TimeUnit unit)
throws InterruptedException {
return completionQueue.poll(timeout, unit);
}
}