天天看點

定制并發類(三)實作一個基于優先級的Executor類

實作一個基于優先級的executor類

在java并發api的第一個版本中,你必須建立和運作應用程式中的所有線程。在java版本5中,随着執行者架構(executor framework)的出現,對于并發任務的執行,一個新的機制被引進。

使用執行者架構(executor framework),你隻要實作你的任務并把它們送出給執行者。這個執行者負責執行你的任務的線程的建立和執行。

在内部,一個執行者使用一個阻塞隊列來存儲待處理任務。以任務到達執行者的順序來存儲。一個可能的替代就是使用一個優先級列隊來存儲新的任務。這樣,如果一個高優先級的新任務到達執行者,它将比其他已經在等待一個線程來執行它們,且低優先級的任務先執行。

在這個指南中,你将學習如何實作一個執行者,它将使用優先級隊列來存儲你送出執行的任務。

準備工作

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

如何做…

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

1.建立一個myprioritytask類,它實作runnable接口和參數化為myprioritytask類的comparable接口。

<code>1</code>

<code>public</code> <code>class</code> <code>myprioritytask</code><code>implements</code> <code>runnable,</code>

<code>2</code>

<code>comparable&lt;myprioritytask&gt; {</code>

2.聲明一個私有的、int類型的屬性priority。

<code>private</code> <code>int</code> <code>priority;</code>

3.聲明一個私有的、string類型的屬性name。

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

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

<code>public</code> <code>myprioritytask(string name,</code><code>int</code> <code>priority) {</code>

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

<code>3</code>

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

<code>4</code>

<code>}</code>

5.實作一個方法來傳回priority屬性的值。

<code>public</code> <code>int</code> <code>getpriority(){</code>

<code>return</code> <code>priority;</code>

6.實作聲明在comparable接口中的compareto()方法。它接收一個myprioritytask對象作為參數,比較這兩個對象(目前對象和參數對象)的優先級。讓優先級高的任務先于優先級低的任務執行。

<code>01</code>

<code>@override</code>

<code>02</code>

<code>public</code> <code>int</code> <code>compareto(myprioritytask o) {</code>

<code>03</code>

<code>if</code> <code>(</code><code>this</code><code>.getpriority() &lt; o.getpriority()) {</code>

<code>04</code>

<code>return</code> <code>1</code><code>;</code>

<code>05</code>

<code>06</code>

<code>if</code> <code>(</code><code>this</code><code>.getpriority() &gt; o.getpriority()) {</code>

<code>07</code>

<code>return</code> <code>-</code><code>1</code><code>;</code>

<code>08</code>

<code>09</code>

<code>return</code> <code>0</code><code>;</code>

<code>10</code>

7.實作run()方法。令目前線程睡眠2秒。

<code>public</code> <code>void</code> <code>run() {</code>

<code>system.out.printf("myprioritytask: %s priority :</code>

<code>%d\n",name,priority);</code>

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

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

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

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

8.實作這個例子的主類,通過建立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>

9.建立一個threadpoolexecutor對象,名為executor。使用參數化為runnable接口的priorityblockingqueue作為執行者用來存儲待處理任務的隊列。

<code>threadpoolexecutor executor=</code><code>new</code> <code>threadpoolexecutor(</code><code>2</code><code>,</code><code>2</code><code>,</code><code>1</code><code>,timeu</code>

<code>nit.seconds,</code><code>new</code> <code>priorityblockingqueue&lt;runnable&gt;());</code>

10.送出4個使用循環計數器作為優先級的任務給執行者。使用execute()方法送出這些任務給執行者。

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

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

<code>executor.execute(task);</code>

11.令目前線程睡眠1秒。

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

<code>5</code>

12.送出4個額外的,使用循環計數器作為優先級的任務給執行者。使用execute()方法送出這些任務給執行者。

<code>for</code> <code>(</code><code>int</code> <code>i=</code><code>4</code><code>; i&lt;</code><code>8</code><code>; i++) {</code>

13.使用shutdown()方法關閉這個執行者。

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

14.使用awaittermination()方法等待這個執行者的結束。

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

15.寫入一條資訊表明這個程式的結束。

<code>system.out.printf(</code><code>"main: end of the program.\n"</code><code>);</code>

它是如何工作的…

很容易将執行者轉換成一個基于優先級的(執行者)。你隻要傳入一個參數化為runnable接口的priorityblockingqueue對象作為參數。但是,使用執行者時,你應該知道存儲在優先級列隊中的所有對象必須實作comparable接口。

你已經實作了myprioritytask類,(作為一個任務)它實作了runnable接口和comparable接口,它被存儲在優先級隊列中。這個類有一個priority屬性,用來存儲任務的優先級。如果一個任務的這個屬性有更高的值,它将被更早的執行。compareto()方法決定任務在優先級列隊中的順序。在main類,你送出8個不同優先級的任務給執行者。你送出給執行者的第一個任務将第一個被執行。由于執行者閑置的,正在等待任務被執行,當第一個任務到達執行者時,執行者立即執行它們。你已經建立有2個執行線程的執行者,是以,前兩個任務将第一個被執行。然後,剩下的任務将按它們的優先級來執行。

以下截圖顯示了示例的一次執行:

定制并發類(三)實作一個基于優先級的Executor類

不止這些…

你可以使用任何實作blockingqueue接口(的隊列)來配置執行者。delayqueue是一個有趣的實作。這個類被用來存儲延遲激活(delayed activation)的元素。它提供隻傳回活動對象的方法。你可以使用這個類來實作自己版本的scheduledthreadpoolexecutor類。

繼續閱讀