1. 程式人生 > >七. 多線程編程7.線程優先級

七. 多線程編程7.線程優先級

lee rgs 有時 sta class oid 主線程 false 自然

線程優先級被線程調度用來判定何時每個線程允許運行。理論上,優先級高的線程比優先級低的線程獲得更多的CPU時間。實際上,線程獲得的CPU時間通常由包括優先級在內的多個因素決定(例如,一個實行多任務處理的操作系統如何更有效的利用CPU時間)。

一個優先級高的線程自然比優先級低的線程優先。舉例來說,當低優先級線程正在運行,而一個高優先級的線程被恢復(例如從沈睡中或等待I/O中),它將搶占低優先級線程所使用的CPU。

理論上,等優先級線程有同等的權利使用CPU。但你必須小心了。記住,Java是被設計成能在很多環境下工作的。一些環境下實現多任務處理從本質上與其他環境不同。為安全起見,等優先級線程偶爾也受控制。這保證了所有線程在無優先級的操作系統下都有機會運行。實際上,在無優先級的環境下,多數線程仍然有機會運行,因為很多線程不可避免的會遭遇阻塞,例如等待輸入輸出。遇到這種情形,阻塞的線程掛起,其他線程運行。

但是如果你希望多線程執行的順利的話,最好不要采用這種方法。同樣,有些類型的任務是占CPU的。對於這些支配CPU類型的線程,有時你希望能夠支配它們,以便使其他線程可以運行。

設置線程的優先級,用setPriority()方法,該方法也是Tread 的成員。它的通常形式為:
final void setPriority(int level)

這 裏 , level 指 定了對所調用的線程的新的優先權的設置。Level的值必須在MIN_PRIORITY到MAX_PRIORITY範圍內。通常,它們的值分別是1和10。要返回一個線程為默認的優先級,指定NORM_PRIORITY,通常值為5。這些優先級在Thread中都被定義為final型變量。

你可以通過調用Thread的getPriority()方法來獲得當前的優先級設置。該方法如下:
final int getPriority( )

當涉及調度時,Java的執行可以有本質上不同的行為。Windows 95/98/NT/2000 的工作或多或少如你所願。但其他版本可能工作的完全不同。大多數矛盾發生在你使用有優先級行為的線程,而不是協同的騰出CPU時間。最安全的辦法是獲得可預先性的優先權,Java獲得跨平臺的線程行為的方法是自動放棄對CPU的控制。

下面的例子闡述了兩個不同優先級的線程,運行於具有優先權的平臺,這與運行於無優先級的平臺不同。一個線程通過Thread.NORM_PRIORITY設置了高於普通優先級兩級的級數,另一線程設置的優先級則低於普通級兩級。兩線程被啟動並允許運行10秒。每個線程執行一個循環,記錄反復的次數。10秒後,主線程終止了兩線程。每個線程經過循環的次數被顯示。
// Demonstrate thread priorities.
class clicker implements Runnable {
int click = 0;
Thread t;
private volatile boolean running = true;
public clicker(int p) {
t = new Thread(this);
t.setPriority(p);
}

public void run() {
while (running) {
click++;
}
}

public void stop() {
running = false;
}

public void start() {
t.start();
}
}

class HiLoPri {
public static void main(String args[]) {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
clicker hi = new clicker(Thread.NORM_PRIORITY + 2);
clicker lo = new clicker(Thread.NORM_PRIORITY - 2);
lo.start();
hi.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
lo.stop();
hi.stop();
// Wait for child threads to terminate.
try {
hi.t.join();
lo.t.join();
} catch (InterruptedException e quqiongyule2.com ) {
System.out.println("InterruptedException caught");
}

System.out.println("Low-priority thread: " + lo.click);
System.out.println("High-priority thread: " + hi.click);
}
}

該程序在Windows 98下運行的輸出,表明線程確實上下轉換,甚至既不屈從於CPU,也不被輸入輸出阻塞。優先級高的線程獲得大約90%的CPU時間。
Low-priority thread: 4408112
High-priority thread: 589626904

當然,該程序的精確的輸出結果依賴於你的CPU的速度和運行的其他任務的數量。當同樣的程序運行於無優先級的系統,將會有不同的結果。

上述程序還有個值得註意的地方。註意running前的關鍵字volatile。盡管volatile 在下章會被很仔細的討論,用在此處以確保running的值在下面的循環中每次都得到驗證。
while (running) {
click++;
}

如果不用volatile,Java可以自由的優化循環:running的值被存在CPU的一個寄存器中,
每次重復不一定需要復檢。volatile的運用阻止了該優化,告知Java running可以改變,改變
方式並不以直接代碼形式顯示。

七. 多線程編程7.線程優先級