1. 程式人生 > >執行緒管理(二)獲取和設定執行緒資訊

執行緒管理(二)獲取和設定執行緒資訊

宣告:本文是《 Java 7 Concurrency Cookbook 》的第一章, 作者: Javier Fernández González 譯者:鄭玉婷 校對:歐振聰

獲取和設定執行緒資訊

Thread類的物件中儲存了一些屬性資訊能夠幫助我們來辨別每一個執行緒,知道它的狀態,調整控制其優先順序。 這些屬性是:

  • ID: 每個執行緒的獨特標識。
  • Name: 執行緒的名稱。
  • Priority: 執行緒物件的優先順序。優先級別在1-10之間,1是最低階,10是最高階。不建議改變它們的優先順序,但是你想的話也是可以的。
  • Status: 執行緒的狀態。在Java中,執行緒只能有這6種中的一種狀態: new, runnable, blocked, waiting, time waiting, 或 terminated.

在這個指南里,我們將開發一個為10個執行緒設定名字和優先順序的程式,然後展示它們的狀態資訊直到執行緒結束。這些執行緒會計算數字乘法表。

準備

指南中的例子是使用Eclipse IDE 來實現的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 開啟並建立一個新的java專案。

怎麼做呢

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

1.   建立一個類名為 Calculator,這個類一定要實現Runnable介面。

public class Calculator implements Runnable {

2.   宣告一個名為number的private int為屬性,然後實現類的建構函式並初始化其值。

private int number;
public Calculator(int number) {
   this.number=number;
}

3.   實現方法run()。此方法是給我們建立的執行緒執行下達指令的,所以這個方法將計算並且列印數字乘法表。

@Override
public void run() {
for (int i=1; i<=10; i++){
   System.out.printf("%s: %d * %d = %d\n",Thread. currentThread().getName(),number,i,i*number);
}
}

4.   現在, 實現應用的主類。建立一個名為Main的類,幷包含 main() 方法.

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

5.  建立一個大小為10的Thread類的陣列和一個大小為10的Thread.State陣列來儲存將要執行的執行緒和它們的狀態。

Thread threads[]=new Thread[10];
Thread.State status[]=new Thread.State[10];

6.    建立10個Calculator類的物件,每個初始為不同的數字,然後分別用10個執行緒來執行它們。把其中5個的優先值設為最高,把另外5個的優先值為最低。

for (int i=0; i<10; i++){
   threads[i]=new Thread(new Calculator(i));
   if ((i%2)==0){
      threads[i].setPriority(Thread.MAX_PRIORITY);
   } else {
      threads[i].setPriority(Thread.MIN_PRIORITY);
   }
   threads[i].setName("Thread "+i);
}

7.   建立一個 PrintWriter物件用於把執行緒狀態的改變寫入文件。

try (FileWriter file = new FileWriter(".\\data\\log.txt"); PrintWriter pw = new PrintWriter(file);){

8.   把10個執行緒的狀態寫入文件。現在,它成為NEW.

for (int i=0; i<10; i++){
   pw.println("Main : Status of Thread "+i+" : " +threads[i].getState());
   status[i]=threads[i].getState();
}

9.   開始執行這10個執行緒.

for (int i=0; i<10; i++){
   threads[i].start();
}

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

boolean finish=false;
while (!finish) {
   for (int i=0; i<10; i++){
      if (threads[i].getState()!=status[i]) {
          writeThreadInfo(pw, threads[i],status[i]);
          status[i]=threads[i].getState();
      }
   }

   finish=true;
   for (int i=0; i<10; i++){
      finish=finish && (threads[i].getState()==State.TERMINATED);
   }
}

11. 實現一個方法 writeThreadInfo(),這個方法寫執行緒的 ID, name, priority, old status, 和 new status。

private static void writeThreadInfo(PrintWriter pw, Thread thread, State state) {
   pw.printf("Main : Id %d - %s\n",thread.getId(),thread.getName());
   pw.printf("Main : Priority: %d\n",thread.getPriority());
   pw.printf("Main : Old State: %s\n",state);
   pw.printf("Main : New State: %s\n",thread.getState());
   pw.printf("Main : ************************************\n");
}

12. 執行這個例子,然後開啟 log.txt 文件並檢視10個執行緒的狀態變化。

它是如何工作的

接下來是程式在執行的log.txt文字的一些行的裁圖。在這個文字中,可以發現有高優先順序的執行緒們比低優先順序的先結束。還可以發現執行緒狀態的演變過程。
1-2

程式的控制檯顯示的是執行緒計算的乘法表,而log.txt文字記錄的是不同執行緒的狀態演變。這樣子,可以更好的觀察執行緒的演變過程。

Thread 類有能儲存使用執行緒資訊的屬性。JVM根據執行緒的優先順序來選擇將使用CPU的執行緒,然後再根據每個執行緒的情況來實現它們的狀態。

如果你沒有宣告一個執行緒的名字,那麼JVM會自動命名它為:Thread-XX,XX是一個數字。執行緒的ID或者狀態是不可修改的。Thread類沒有實現setId()和setStatus()方法來允許修改它們。

更多

在這個指南中,你學習瞭如何使用Thread物件來訪問執行緒的屬性資訊。你也可以實現Runnable介面來訪問這些資訊。你可以用Thread類的靜態方法currentThread()來訪問正在執行的Runnable 物件的 Thread物件。

你必須知道 setPriority() 方法會丟擲 IllegalArgumentException 異常,如果你設定的優先順序不是在1-10之間。

參見

  • 第一章,執行緒管理:執行緒的中斷