標籤:
線程優先順序被線程調度用來判定何時每個線程允許運行。理論上,優先順序高的線程比優先順序低的線程獲得更多的CPU時間。實際上,線程獲得的CPU時間通常由包括優先順序在內的多個因素決定(例如,一個實行多任務處理的作業系統如何更有效利用CPU時間)。
一個優先順序高的線程自然比優先順序低的線程優先。舉例來說,當低優先順序線程正在運行,而一個高優先順序的線程被恢複(例如從沉睡中或等待I/O中),它將搶佔低優先順序線程所使用的CPU。
理論上,等優先順序線程有同等的權利使用CPU。但你必須小心了。記住,Java是被設計成能在很多環境下工作的。一些環境下實現多任務處理從本質上與其他環境不同。為安全起見,等優先順序線程偶爾也受控制。這保證了所有線程在無優先順序的作業系統下都有機會運行。實際上,在無優先順序的環境下,多數線程仍然有機會運行,因為很多線程不可避免的會遭遇阻塞,例如等待輸入輸出。遇到這種情形,阻塞的線程掛起,其他線程運行。
但是如果你希望多線程執行的順利的話,最好不要採用這種方法。同樣,有些類型的任務是占CPU的。對於這些支配CPU類型的線程,有時你希望能夠支配它們,以便使其他線程可以運行。
設定線程的優先順序,用setPriority()方法,該方法也是Tread 的成員。它的通常形式為:
1 final void setPriority(int level)
這 裡 , level 指 定了對所調用的線程的新的優先權的設定。Level的值必須在MIN_PRIORITY到MAX_PRIORITY範圍內。通常,它們的值分別是1和10。要返回一個線程為預設的優先順序,指定NORM_PRIORITY,通常值為5。這些優先順序在Thread中都被定義為final型變數。
你可以通過調用Thread的getPriority()方法來獲得當前的優先順序設定。該方法如下:
1 final int getPriority( )
當涉及調度時,Java的執行可以有本質上不同的行為。Windows 95/98/NT/2000 的工作或多或少如你所願。但其他版本可能工作的完全不同。大多數矛盾發生在你使用有優先順序行為的線程,而不是協同的騰出CPU時間。最安全的辦法是獲得可預先性的優先權,Java獲得跨平台的線程行為的方法是自動放棄對CPU的控制。
下面的例子闡述了兩個不同優先順序的線程,運行於具有優先權的平台,這與運行於無優先順序的平台不同。一個線程通過Thread.NORM_PRIORITY設定了高於普通優先順序兩級的級數,另一線程設定的優先順序則低於普通級兩級。兩線程被啟動並允許運行10秒。每個線程執行一個迴圈,記錄反覆的次數。10秒後,主線程終止了兩線程。每個線程經過迴圈的次數被顯示。
1 // Demonstrate thread priorities. 2 class clicker implements Runnable { 3 int click = 0; 4 Thread t; 5 private volatile boolean running = true; 6 public clicker(int p) { 7 t = new Thread(this); 8 t.setPriority(p); 9 }10 11 public void run() {12 while (running) {13 click++;14 }15 }16 17 public void stop() {18 running = false;19 }20 21 public void start() {22 t.start();23 }24 }25 26 class HiLoPri {27 public static void main(String args[]) {28 Thread.currentThread().setPriority(Thread.MAX_PRIORITY);29 clicker hi = new clicker(Thread.NORM_PRIORITY + 2);30 clicker lo = new clicker(Thread.NORM_PRIORITY - 2);31 lo.start();32 hi.start();33 try {34 Thread.sleep(10000);35 } catch (InterruptedException e) {36 System.out.println("Main thread interrupted.");37 }38 lo.stop();39 hi.stop();40 // Wait for child threads to terminate.41 try {42 hi.t.join();43 lo.t.join();44 } catch (InterruptedException e) {45 System.out.println("InterruptedException caught");46 }47 48 System.out.println("Low-priority thread: " + lo.click);49 System.out.println("High-priority thread: " + hi.click);50 }51 }
該程式在Windows 98下啟動並執行輸出,表明線程確實上下轉換,甚至既不屈從於CPU,也不被輸入輸出阻塞。優先順序高的線程獲得大約90%的CPU時間。
Low-priority thread: 4408112High-priority thread: 589626904
當然,該程式的精確的輸出結果依賴於你的CPU的速度和啟動並執行其他任務的數量。當同樣的程式運行於無優先順序的系統,將會有不同的結果。
上述程式還有個值得注意的地方。注意running前的關鍵字volatile。儘管volatile 在下章會被很仔細的討論,用在此處以確保running的值在下面的迴圈中每次都得到驗證。
1 while (running) {2 click++;3 }
如果不用volatile,Java可以自由的最佳化迴圈:running的值被存在CPU的一個寄存器中,
每次重複不一定需要複檢。volatile的運用阻止了該最佳化,告知Java running可以改變,改變
方式並不以直接代碼形式顯示。
系列文章:
Java知多少(上)
Java知多少(39)interface介面
Java知多少(40)介面和抽象類別的區別
Java知多少(41)泛型詳解
Java知多少(42)泛型萬用字元和型別參數的範圍
Java知多少(43)異常處理基礎
Java知多少(44)異常類型
Java知多少(45)未被捕獲的異常
Java知多少(46)try和catch的使用
Java知多少(47)多重catch語句的使用
Java知多少(48)try語句的嵌套
Java知多少(49)throw:異常的拋出
Java知多少(50)Java throws子句
Java知多少(51)finally
Java知多少(52)內建異常
Java知多少(53)使用Java建立自己的異常子類
Java知多少(54)斷言詳解
Java知多少(55)線程
Java知多少(56)執行緒模式Java知多少(57)主線程Java知多少(58)線程Runnable介面和Thread類詳解Java知多少(59)建立多線程Java知多少(60)isAlive()和join()的使用
Java知多少(61)線程優先順序