天天看點

線程執行者(七)執行者延遲運作一個任務

執行者延遲運作一個任務

執行者架構提供threadpoolexecutor類,使用池中的線程來執行callable和runnable任務,這樣可以避免所有線程的建立操作。當你送出一個任務給執行者,會根據執行者的配置盡快執行它。在有些使用情況下,當你對盡快執行任務不感覺興趣。你可能想要在一段時間之後執行任務或周期性地執行任務。基于這些目的,執行者架構提供 scheduledthreadpoolexecutor類。

在這個指南中,你将學習如何建立scheduledthreadpoolexecutor和如何使用它安排任務在指定的時間後執行。

準備工作…

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

如何做…

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

1.建立task類,實作callable接口,參數化為string類型。

<code>1</code>

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

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

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

3.實作task類的構造器,初始化name屬性。

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

<code>2</code>

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

<code>3</code>

<code>}</code>

4.實作call()方法,寫入實際日期到控制台,傳回一個文本,如:hello, world。

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

<code>system.out.printf(</code><code>"%s: starting at : %s\n"</code><code>,name,</code><code>new</code> <code>date());</code>

<code>return</code> <code>"hello, world"</code><code>;</code>

<code>4</code>

5.實作示例的主類,建立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>

6.使用executors類的newscheduledthreadpool()方法,建立scheduledthreadpoolexecutor類的一個執行者。傳入參數1。

<code>scheduledthreadpoolexecutor executor=(scheduledthreadpoolexecutor)executors.newscheduledthreadpool(</code><code>1</code><code>);</code>

7.使用scheduledthreadpoolexecutor執行個體的schedule()方法,初始化和開始一些任務(本例中5個任務)。

<code>system.out.printf(</code><code>"main: starting at: %s\n"</code><code>,</code><code>new</code> <code>date());</code>

<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>task task=</code><code>new</code> <code>task(</code><code>"task "</code><code>+i);</code>

<code>executor.schedule(task,i+</code><code>1</code> <code>, timeunit.seconds);</code>

<code>5</code>

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

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

9.使用執行者的awaittermination()方法,等待所有任務完成。

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

<code>executor.awaittermination(</code><code>1</code><code>, timeunit.days);</code>

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

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

10.寫入一條資訊表明程式結束時間。

<code>system.out.printf(</code><code>"main: ends at: %s\n"</code><code>,</code><code>new</code> <code>date());</code>

它是如何工作的…

在這個示例中,關鍵的一點是main類和scheduledthreadpoolexecutor的管理。正如使用threadpoolexecutor類建立預定的執行者,java建議利用executors類。在本例中,你使用newscheduledthreadpool()方法。你用1作為參數傳給這個方法。這個參數是你想要讓線程池建立的線程數。

你必須使用schedule()方法,讓執行者在一段時間後執行任務。這個方法接收3個參數,如下:

你想要執行的任務

你想要讓任務在執行前等待多長時間

時間機關,指定為timeunit類的常數

在本例中,每個任務等待的秒數(timeunit.seconds)等于它在任務數組中的位置再加1。

注意事項:如果你想在給定時間執行一個任務,計算這個日期與目前日期的差異,使用這個差異作為任務的延遲。

以下截圖顯示這個示例執行的輸出:

線程執行者(七)執行者延遲運作一個任務

你可以看出這些任務是如何開始執行的,一秒執行一個。所有任務都是同時送出給執行者的,但每個任務比之前的任務都有1秒的延遲。

不止這些…

你也可以使用runnable接口實作任務,因為scheduledthreadpoolexecutor類的schedule()方法接收這兩種類型(runnable和callable)的任務。

盡管scheduledthreadpoolexecutor類是threadpoolexecutor類的子類,是以,它繼承 threadpoolexecutor類的所有功能,但java建議使用scheduledthreadpoolexecutor僅适用于排程任務。

最後,你可以配置scheduledthreadpoolexecutor的行為,當你調用shutdown()方法時,并且有待處理的任務正在等待它們延遲結束。預設的行為是,不管執行者是否結束這些任務都将被執行。你可以使用scheduledthreadpoolexecutor類的setexecuteexistingdelayedtasksaftershutdownpolicy()方法來改變這種行為。使用false,調用 shutdown()時,待處理的任務不會被執行。

參見

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

繼續閱讀