天天看點

線程管理(二)擷取和設定線程資訊

thread類的對象中儲存了一些屬性資訊能夠幫助我們來辨識每一個線程,知道它的狀态,調整控制其優先級。 這些屬性是:

id: 每個線程的獨特辨別。

name: 線程的名稱。

priority: 線程對象的優先級。優先級别在1-10之間,1是最低級,10是最進階。不建議改變它們的優先級,但是你想的話也是可以的。

status: 線程的狀态。在java中,線程隻能有這6種中的一種狀态: new, runnable, blocked, waiting, time waiting, 或 terminated.

在這個指南裡,我們将開發一個為10個線程設定名字和優先級的程式,然後展示它們的狀态資訊直到線程結束。這些線程會計算數字乘法表。

<b>準備</b>

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

怎麼做呢<b>…</b>

按照這些步驟來實作下面的例子:

1.   建立一個類名為 calculator,這個類一定要實作runnable接口。

<code>1</code>

<code>public</code> <code>class</code> <code>calculator</code><code>implements</code> <code>runnable {</code>

2.   聲明一個名為number的private int為屬性,然後實作類的構造函數并初始化其值。

<code>private</code> <code>int</code> <code>number;</code>

<code>2</code>

<code>public</code> <code>calculator(</code><code>int</code> <code>number) {</code>

<code>3</code>

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

<code>4</code>

<code>}</code>

3.   實作方法run()。此方法是給我們建立的線程執行下達指令的,是以這個方法将計算并且列印數字乘法表。

<code>@override</code>

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

<code>for</code> <code>(</code><code>int</code> <code>i=</code><code>1</code><code>; i&lt;=</code><code>10</code><code>; i++){</code>

<code>   </code><code>system.out.printf(</code><code>"%s: %d * %d = %d\n"</code><code>,thread. currentthread().getname(),number,i,i*number);</code>

<code>5</code>

<code>6</code>

4.   現在, 實作應用的主類。建立一個名為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>

5.  建立一個大小為10的thread類的數組和一個大小為10的thread.state數組來儲存将要執行的線程和它們的狀态。

<code>thread threads[]=</code><code>new</code> <code>thread[</code><code>10</code><code>];</code>

<code>thread.state status[]=</code><code>new</code> <code>thread.state[</code><code>10</code><code>];</code>

6.    建立10個calculator類的對象,每個初始為不同的數字,然後分别用10個線程來運作它們。把其中5個的優先值設為最高,把另外5個的優先值為最低。

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

<code>   </code><code>threads[i]=</code><code>new</code> <code>thread(</code><code>new</code> <code>calculator(i));</code>

<code>   </code><code>if</code> <code>((i%</code><code>2</code><code>)==</code><code>0</code><code>){</code>

<code>      </code><code>threads[i].setpriority(thread.max_priority);</code>

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

<code>      </code><code>threads[i].setpriority(thread.min_priority);</code>

<code>7</code>

<code>   </code><code>}</code>

<code>8</code>

<code>   </code><code>threads[i].setname(</code><code>"thread "</code><code>+i);</code>

<code>9</code>

7.   建立一個 printwriter對象用于把線程狀态的改變寫入文檔。

<code>try</code> <code>(filewriter file =</code><code>new</code> <code>filewriter(</code><code>".\\data\\log.txt"</code><code>); printwriter pw =</code><code>new</code> <code>printwriter(file);){</code>

8.   把10個線程的狀态寫入文檔。現在,它成為new.

<code>   </code><code>pw.println(</code><code>"main : status of thread "</code><code>+i+</code><code>" : "</code> <code>+threads[i].getstate());</code>

<code>   </code><code>status[i]=threads[i].getstate();</code>

9.   開始執行這10個線程.

<code>   </code><code>threads[i].start();</code>

10. 直到這10個線程執行結束,我們會一直檢查它們的狀态。如果發現它的狀态改變,就把狀态記入文本。

<code>01</code>

<code>boolean</code> <code>finish=</code><code>false</code><code>;</code>

<code>02</code>

<code>while</code> <code>(!finish) {</code>

<code>03</code>

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

<code>04</code>

<code>      </code><code>if</code> <code>(threads[i].getstate()!=status[i]) {</code>

<code>05</code>

<code>          </code><code>writethreadinfo(pw, threads[i],status[i]);</code>

<code>06</code>

<code>          </code><code>status[i]=threads[i].getstate();</code>

<code>07</code>

<code>      </code><code>}</code>

<code>08</code>

<code>09</code>

<code>10</code>

<code>   </code><code>finish=</code><code>true</code><code>;</code>

<code>11</code>

<code>12</code>

<code>      </code><code>finish=finish &amp;&amp; (threads[i].getstate()==state.terminated);</code>

<code>13</code>

<code>14</code>

11. 實作一個方法 writethreadinfo(),這個方法寫線程的 id, name, priority, old status, 和 new status。

<code>private</code> <code>static</code> <code>void</code> <code>writethreadinfo(printwriter pw, thread thread, state state) {</code>

<code>   </code><code>pw.printf(</code><code>"main : id %d - %s\n"</code><code>,thread.getid(),thread.getname());</code>

<code>   </code><code>pw.printf(</code><code>"main : priority: %d\n"</code><code>,thread.getpriority());</code>

<code>   </code><code>pw.printf(</code><code>"main : old state: %s\n"</code><code>,state);</code>

<code>   </code><code>pw.printf(</code><code>"main : new state: %s\n"</code><code>,thread.getstate());</code>

<code>   </code><code>pw.printf(</code><code>"main : ************************************\n"</code><code>);</code>

12. 運作這個例子,然後打開 log.txt 文檔并檢視10個線程的狀态變化。

它是如何工作的<b>…</b>

接下來是程式在執行的log.txt文本的一些行的裁圖。在這個文本中,可以發現有高優先級的線程們比低優先級的先結束。還可以發現線程狀态的演變過程。

線程管理(二)擷取和設定線程資訊

程式的控制台顯示的是線程計算的乘法表,而log.txt文本記錄的是不同線程的狀态演變。這樣子,可以更好的觀察線程的演變過程。

thread 類有能儲存使用線程資訊的屬性。jvm根據線程的優先級來選擇将使用cpu的線程,然後再根據每個線程的情況來實作它們的狀态。

如果你沒有聲明一個線程的名字,那麼jvm會自動命名它為:thread-xx,xx是一個數字。線程的id或者狀态是不可修改的。thread類沒有實作setid()和setstatus()方法來允許修改它們。

更多<b>…</b>

在這個指南中,你學習了如何使用thread對象來通路線程的屬性資訊。你也可以實作runnable接口來通路這些資訊。你可以用thread類的靜态方法currentthread()來通路正在運作的runnable 對象的 thread對象。

你必須知道 setpriority() 方法會抛出 illegalargumentexception 異常,如果你設定的優先級不是在1-10之間。

參見

第一章,線程管理:線程的中斷

繼續閱讀