天天看點

線程執行者(十)執行者控制一個任務完成

執行者控制一個任務完成

futuretask類提供一個done()方法,允許你在執行者執行任務完成後執行一些代碼。你可以用來做一些後處理操作,生成一個報告,通過e-mail發送結果,或釋放一些資源。當執行的任務由futuretask來控制完成,futuretask會内部調用這個方法。這個方法在任務的結果設定和它的狀态變成isdone狀态之後被調用,不管任務是否已經被取消或正常完成。

預設情況下,這個方法是空的。你可以重寫futuretask類實作這個方法來改變這種行為。在這個指南中,你将學習如何重寫這個方法,在任務完成之後執行代碼。

準備工作…

這個指南的例子使用eclipse ide實作。如果你使用eclipse或其他ide,如netbeans,打開它并建立一個新的java項目。

如何做…

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

1.建立executabletask類,并指定其實作callable接口,參數化為string類型。

<code>1</code>

<code>public</code> <code>class</code> <code>executabletask </code><code>implements</code> <code>callable&lt;string&gt; {</code>

2.聲明一個私有的、類型為string、名為name的屬性,用來存儲任務的名稱。實作getname()方法,傳回這個屬性值。

<code>private</code> <code>string name;</code>

<code>2</code>

<code>public</code> <code>string getname(){</code>

<code>3</code>

<code>return</code> <code>name;</code>

<code>4</code>

<code>}</code>

3.實作這個類的構造器,初始化任務的名稱。

<code>public</code> <code>executabletask(string name){</code>

<code>this</code><code>.name=name;</code>

4.實作call()方法。使這個任務睡眠一個随機時間,傳回任務名稱的資訊。

<code>01</code>

<code>@override</code>

<code>02</code>

<code>public</code> <code>string call() </code><code>throws</code> <code>exception {</code>

<code>03</code>

<code>try</code> <code>{</code>

<code>04</code>

<code>long</code> <code>duration=(</code><code>long</code><code>)(math.random()*</code><code>10</code><code>);</code>

<code>05</code>

<code>system.out.printf("%s: waiting %d seconds </code><code>for</code> <code>results.\</code>

<code>06</code>

<code>n",</code><code>this</code><code>.name,duration);</code>

<code>07</code>

<code>timeunit.seconds.sleep(duration);</code>

<code>08</code>

<code>} </code><code>catch</code> <code>(interruptedexception e) {</code>

<code>09</code>

<code>10</code>

<code>return</code> <code>"hello, world. i'm "</code><code>+name;</code>

<code>11</code>

5.實作resulttask類,繼承futuretask類,參數化為string類型。

<code>public</code> <code>class</code> <code>resulttask </code><code>extends</code> <code>futuretask&lt;string&gt; {</code>

6.聲明一個私有的、類型為string、名為name的屬性,用來存儲任務的名稱。

7.實作這個類的構造器。它接收一個callable對象參數。調用父類構造器,使用接收到的任務的屬性初始化name屬性。

<code>public</code> <code>resulttask(callable&lt;string&gt; callable) {</code>

<code>super</code><code>(callable);</code>

<code>this</code><code>.name=((executabletask)callable).getname();</code>

8.重寫done()方法。檢查iscancelled()方法傳回值,并根據這個傳回值的不同,寫入不同的資訊到控制台。

<code>protected</code> <code>void</code> <code>done() {</code>

<code>if</code> <code>(iscancelled()) {</code>

<code>system.out.printf(</code><code>"%s: has been canceled\n"</code><code>,name);</code>

<code>5</code>

<code>} </code><code>else</code> <code>{</code>

<code>6</code>

<code>system.out.printf(</code><code>"%s: has finished\n"</code><code>,name);</code>

<code>7</code>

<code>8</code>

9.實作示例的主類,建立main類,實作main()方法。

<code>public</code> <code>class</code> <code>main {</code>

<code>public</code> <code>static</code> <code>void</code> <code>main(string[] args) {</code>

10.使用executors類的newcachedthreadpool()方法建立executorservice。

<code>executorservice executor=(executorservice)executors.newcachedthreadpool();</code>

11.建立存儲5個resulttask對象的一個數組。

<code>resulttask resulttasks[]=</code><code>new</code> <code>resulttask[</code><code>5</code><code>];</code>

12.初始化resulttask對象。對于資料的每個位置,首先,你必須建立executortask,然後,resulttask使用這個對象,然後,然後submit()方法送出resulttask給執行者。

<code>for</code> <code>(</code><code>int</code> <code>i=</code><code>0</code><code>; i&lt;</code><code>5</code><code>; i++) {</code>

<code>executabletask executabletask=</code><code>new</code> <code>executabletask(</code><code>"task "</code><code>+i);</code>

<code>resulttasks[i]=</code><code>new</code> <code>resulttask(executabletask);</code>

<code>executor.submit(resulttasks[i]);</code>

13.令主線程睡眠5秒。

<code>timeunit.seconds.sleep(</code><code>5</code><code>);</code>

<code>} </code><code>catch</code> <code>(interruptedexception e1) {</code>

<code>e1.printstacktrace();</code>

14.取消你送出給執行者的所有任務。

<code>for</code> <code>(</code><code>int</code> <code>i=</code><code>0</code><code>; i&lt;resulttasks.length; i++) {</code>

<code>resulttasks[i].cancel(</code><code>true</code><code>);</code>

15.将沒有被使用resulttask對象的get()方法取消的任務的結果寫入到控制台。

<code>if</code> <code>(!resulttasks[i].iscanceled()){</code>

<code>system.out.printf(</code><code>"%s\n"</code><code>,resulttasks[i].get());</code>

<code>} </code><code>catch</code> <code>(interruptedexception | executionexception e) {</code>

<code>e.printstacktrace();</code>

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

<code>executor.shutdown();</code>

它是如何工作的…

當控制任務執行完成後,futuretask類調用done()方法。在這個示例中,你已經實作一個callable對象,executabletask類,然後一個futuretask類的子類用來控制executabletask對象的執行。

在建立傳回值和改變任務的狀态為isdone狀态後,done()方法被futuretask類内部調用。你不能改變任務的結果值和它的狀态,但你可以關閉任務使用的資源,寫日志消息,或發送通知。

參見

在第4章,線程執行者中的執行者執行傳回結果的任務指南

繼續閱讀