1. 程式人生 > >執行緒執行者(十二)執行者控制被拒絕的任務

執行緒執行者(十二)執行者控制被拒絕的任務

宣告:本文是《 Java 7 Concurrency Cookbook 》的第四章,作者: Javier Fernández González     譯者:許巧輝     校對:方騰飛,葉磊

執行者控制被拒絕的任務

當你想要結束執行者的執行,你使用shutdown()方法來表明它的結束。執行者等待正在執行或等待它的執行的任務的結束,然後結束它們的執行。

如果你在shutdown()方法和執行者結束之間,提交任務給執行者,這個任務將被拒絕,因為執行者不再接收新的任務。ThreadPoolExecutor類提供一種機制,在呼叫shutdown()後,不接受新的任務。

在這個指南中,你將學習如何通過實現RejectedExecutionHandler,在執行者中管理拒絕任務。

準備工作…

這個指南的例子使用Eclipse IDE實現。如果你使用Eclipse或其他IDE,如NetBeans,開啟它並建立一個新的Java專案。

如何做…

按以下步驟來實現的這個例子:

1.建立RejectedTaskController類,實現RejectedExecutionHandler介面。實現這個介面的rejectedExecution()方法。寫入被拒絕任務的名稱和執行者的名稱與狀態到控制檯。

public class RejectedTaskController implements
RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.printf("RejectedTaskController: The task %s has been rejected\n",r.toString());
System.out.printf("RejectedTaskController: %s\n",executor.toString());
System.out.printf("RejectedTaskController: Terminating:%s\n",executor.isTerminating());
System.out.printf("RejectedTaksController: Terminated:%s\n",executor.isTerminated());
}

2.實現Task類,實現Runnable介面。

public class Task implements Runnable{

3.宣告私有的、String型別的屬性name, 用來儲存任務的名稱。

private String name;

4.實現這個類的構造器,初始化這個類的屬性。

public Task(String name){
this.name=name;
}

5.實現run()方法,寫入資訊到控制檯,表明這個方法開始執行。

@Override
public void run() {
System.out.println("Task "+name+": Starting");

6.等待一段隨機時間。

try {
long duration=(long)(Math.random()*10);
System.out.printf("Task %s: ReportGenerator: Generating a report during %d seconds\n",name,duration);
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}

7.寫入資訊到控制檯,表明方法的結束。

System.out.printf("Task %s: Ending\n",name);
}

8.重寫toString()方法,返回任務的名稱。

public String toString() {
return name;
}

9.實現這個示例的主類,通過建立Main類,並實現main()方法。

public class Main {
public static void main(String[] args) {

10.建立一個RejectedTaskController物件,管理拒絕的任務。

RejectecTaskController controller=new RejectecTaskController();

11.使用Executors類的newCachedThreadPool()方法,建立ThreadPoolExecutor。

ThreadPoolExecutor executor=(ThreadPoolExecutor) Executors.newCachedThreadPool();

12.建立執行者的拒絕任務控制器。

executor.setRejectedExecutionHandler(controller);

13.建立任務並提交它們給執行者。

System.out.printf("Main: Starting.\n");
for (int i=0; i<3; i++) {
Task task=new Task("Task"+i);
executor.submit(task);
}

14.使用shutdown()方法,關閉執行者。

System.out.printf("Main: Shutting down the Executor.\n");
executor.shutdown();

15.建立其他任務並提交給執行者。

System.out.printf("Main: Sending another Task.\n");
Task task=new Task("RejectedTask");
executor.submit(task);

16.寫入資訊到控制檯,表明程式結束。

System.out.println("Main: End");
System.out.printf("Main: End.\n");

這是如何工作的…

以下截圖顯示示例的執行結果:

8

你可以看出當執行者關閉時,任務被拒絕提交。RejectecTaskController將有關於任務和執行者的資訊寫入到控制檯。

為了管理執行者控制拒絕任務,你應該實現RejectedExecutionHandler介面。該介面有帶有兩個引數的方法rejectedExecution():

  • Runnable物件,儲存被拒絕的任務
  • Executor物件,儲存拒絕任務的執行者

每個被執行者拒絕的任務都會呼叫這個方法。你必須使用Executor類的setRejectedExecutionHandler()方法設定拒絕任務的處理器。

不止這些…

當執行者接收任務時,會檢查shutdown()是否已經被呼叫了。如果被呼叫了,它拒絕這個任務。首先,它查詢 setRejectedExecutionHandler()設定的處理器。如果有一個(處理器),它呼叫那個類的 rejectedExecution()方法,否則,它將拋RejectedExecutionExeption異常。這是一個執行時異常,所以你不需要 用catch語句來控制它。

參見

  • 在第4章,執行緒執行者中的建立一個執行緒執行者指南