971
阿裏雲
技術社區[雲棲]
線程執行者(十)執行者控製一個任務完成
聲明:本文是《 Java 7 Concurrency Cookbook 》的第四章,作者: Javier Fernández González 譯者:許巧輝 校對:方騰飛,葉磊
執行者控製一個任務完成
FutureTask類提供一個done()方法,允許你在執行者執行任務完成後執行一些代碼。你可以用來做一些後處理操作,生成一個報告,通過e-mail發送結果,或釋放一些資源。當執行的任務由FutureTask來控製完成,FutureTask會內部調用這個方法。這個方法在任務的結果設置和它的狀態變成isDone狀態之後被調用,不管任務是否已經被取消或正常完成。
默認情況下,這個方法是空的。你可以重寫FutureTask類實現這個方法來改變這種行為。在這個指南中,你將學習如何重寫這個方法,在任務完成之後執行代碼。
準備工作…
這個指南的例子使用Eclipse IDE實現。如果你使用Eclipse或其他IDE,如NetBeans,打開它並創建一個新的Java項目。
如何做…
按以下步驟來實現的這個例子:
1.創建ExecutableTask類,並指定其實現Callable接口,參數化為String類型。
1 |
public class ExecutableTask implements Callable<String> {
|
2.聲明一個私有的、類型為String、名為name的屬性,用來存儲任務的名稱。實現getName()方法,返回這個屬性值。
2 |
public String getName(){
|
3.實現這個類的構造器,初始化任務的名稱。
1 |
public ExecutableTask(String name){
|
4.實現call()方法。使這個任務睡眠一個隨機時間,返回任務名稱的信息。
02 |
public String call() throws Exception {
|
04 |
long duration=( long )(Math.random()* 10 );
|
05 |
System.out.printf("%s: Waiting %d seconds for results.\
|
06 |
n", this .name,duration);
|
07 |
TimeUnit.SECONDS.sleep(duration); |
08 |
} catch (InterruptedException e) {
|
10 |
return "Hello, world. I'm " +name;
|
5.實現ResultTask類,繼承FutureTask類,參數化為String類型。
1 |
public class ResultTask extends FutureTask<String> {
|
6.聲明一個私有的、類型為String、名為name的屬性,用來存儲任務的名稱。
7.實現這個類的構造器。它接收一個Callable對象參數。調用父類構造器,使用接收到的任務的屬性初始化name屬性。
1 |
public ResultTask(Callable<String> callable) {
|
3 |
this .name=((ExecutableTask)callable).getName();
|
8.重寫done()方法。檢查isCancelled()方法返回值,並根據這個返回值的不同,寫入不同的信息到控製台。
2 |
protected void done() {
|
4 |
System.out.printf( "%s: Has been canceled\n" ,name);
|
6 |
System.out.printf( "%s: Has finished\n" ,name);
|
9.實現示例的主類,創建Main類,實現main()方法。
2 |
public static void main(String[] args) {
|
10.使用Executors類的newCachedThreadPool()方法創建ExecutorService。
1 |
ExecutorService executor=(ExecutorService)Executors.newCachedThreadPool(); |
11.創建存儲5個ResultTask對象的一個數組。
1 |
ResultTask resultTasks[]= new ResultTask[ 5 ];
|
12.初始化ResultTask對象。對於數據的每個位置,首先,你必須創建ExecutorTask,然後,ResultTask使用這個對象,然後,然後submit()方法提交ResultTask給執行者。
1 |
for ( int i= 0 ; i< 5 ; i++) {
|
2 |
ExecutableTask executableTask= new ExecutableTask( "Task " +i);
|
3 |
resultTasks[i]= new ResultTask(executableTask);
|
4 |
executor.submit(resultTasks[i]); |
13.令主線程睡眠5秒。
2 |
TimeUnit.SECONDS.sleep( 5 );
|
3 |
} catch (InterruptedException e1) {
|
14.取消你提交給執行者的所有任務。
1 |
for ( int i= 0 ; i<resultTasks.length; i++) {
|
2 |
resultTasks[i].cancel( true );
|
15.將沒有被使用ResultTask對象的get()方法取消的任務的結果寫入到控製台。
01 |
for ( int i= 0 ; i<resultTasks.length; i++) {
|
03 |
if (!resultTasks[i].isCanceled()){
|
04 |
System.out.printf( "%s\n" ,resultTasks[i].get());
|
06 |
} catch (InterruptedException | ExecutionException e) {
|
16.使用shutdown()方法關閉執行者。
它是如何工作的…
當控製任務執行完成後,FutureTask類調用done()方法。在這個示例中,你已經實現一個Callable對象,ExecutableTask類,然後一個FutureTask類的子類用來控製ExecutableTask對象的執行。
在建立返回值和改變任務的狀態為isDone狀態後,done()方法被FutureTask類內部調用。你不能改變任務的結果值和它的狀態,但你可以關閉任務使用的資源,寫日誌消息,或發送通知。
參見
最後更新:2017-05-23 19:31:53