@
Thread 中線程優先級相關屬性
每個線程均有優先級,在 Thread 中, 與優先級對應的屬性如下:
/**
* 線程的優先級屬性
*/
private int priority;
/**
* 線程所能擁有的最大優先級.
*/
public final static int MIN_PRIORITY = 1;
/**
* 線程默認的優先級.
*/
public final static int NORM_PRIORITY = 5;
/**
* 線程所能擁有的最大優先級.
*/
public final static int MAX_PRIORITY = 10;
相關函數
在此只討論 Thread 類中的。
優先級初始化
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
// ....
this.priority = parent.getPriority();
setPriority(priority);
// ....
}
init() 函數對優先級進行了初始化。並調用 setPriority(priority) 函數進行設置。從中得知, 線程的優先級是繼承於創建它的線程的。
設置優先級
在 init() 中, 除了給 this.priority 賦值, 還調用了 setPriority(priority) 函數, 因為在該函數內部還調用了一個 native 方法。
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
// 不能大於最大優先級 MAX_PRIORITY
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {
// 如比所屬線程組的最大優先級還大, 則取線程組的最大優先級
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
}
由代碼可知, 設置的優先級不能大於最大優先級,也不能大於所在線程組的最高優先級
獲取優先級
獲取當前的優先級, 其實就是返回 priority 屬性的值。
public final int getPriority() {
return priority;
}
從以上可知, 在 Thread 中, 線程的優先級有如下特點:
- Java 線程的優先級從 1~10;
- Java 線程默認優先級是 5;
- Java 線程的優先級繼承於創建它的線程。
是不是感覺 2 和 3 有所矛盾呢?可以在后面的代碼和結果中找答案。
默認優先級
先上代碼來感受一下線程優先級的作用:
public class ThreadPriorityTest {
class PrimeRun implements Runnable {
public void run() {
System.out.println(Thread.currentThread().getName() +"::"+
Thread.currentThread().getPriority());
System.out.println(Thread.currentThread().getName() + " Run begin");
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"::"+i);
}
System.out.println(Thread.currentThread().getName() + " Run end");
}
}
public void test(){
System.out.println(Thread.currentThread().getName()+" begin");
Thread p4 = new Thread(new PrimeRun());
Thread p6 = new Thread(new PrimeRun());
p4.setName("P4");
p6.setName("P6");
p4.start();
p6.start();
System.out.println(Thread.currentThread().getName()+" end");
}
public static void main(String[] args) {
new ThreadPriorityTest().test();
}
}
在 PrimeRun 類的 run() 方法中, 只是對 0 到 10 進行輸出, 前面加上線程名字以識別。沒有對線程進行設置, 按以上分析的 init() 方法可知, 優先級繼承於 ThreadPriorityTest 中的優先級, 沒進行設置優先級默認為 5。 輸出如下:

可以看到 p4 和 p6 的線程優先級都是 5, 輸出是無序的, P4 和 P6 交叉輸出, 因此每次的結果都不一樣。
指定優先級
將線程中的優先級改一下, test() 函數變成如下:
public void test(){
System.out.println(Thread.currentThread().getName()+" begin");
Thread p4 = new Thread(new PrimeRun());
Thread p6 = new Thread(new PrimeRun());
p4.setName("P4");
p4.setPriority(4);
p6.setName("P6");
p6.setPriority(6);
p4.start();
p6.start();
System.out.println(Thread.currentThread().getName()+" end");
}
在運行之后的輸出如下:

可以看到, P6 先於 P4 運行完。
注意事項
但是(一般 「但是」 后面的東西都要注意)
優先級和操作系統及虛擬機版本相關。
++優先級只是代表告知了 「線程調度器」該線程的重要度有多大。如果有大量線程都被堵塞,都在等候運
行,調試程序會首先運行具有最高優先級的那個線程。然而,這並不表示優先級較低的線程不會運行(換言之,不會因為存在優先級而導致死鎖)。若線程的優先級較低,只不過表示它被准許運行的機會小一些而已。++
因此, 在實際的編碼時, 認為高優先級一定先於低優先級的線程執行, 最后會出問題的。
優先級繼承
而關於特點 2 和 3 的區別, 我們在第一次 test() 時, P4 和 P6 的優先級都是 5, 我們將函數改一下:
public void test(){
Thread.currentThread().setPriority(10);
System.out.println(Thread.currentThread().getName()+" begin");
Thread p4 = new Thread(new PrimeRun());
Thread p6 = new Thread(new PrimeRun());
p4.setName("P4");
p6.setName("P6");
p4.start();
p6.start();
System.out.println(Thread.currentThread().getName()+" end");
}
在創建 P4 和 P6 之前將當前線程的優先級設置為 10, 並在 run() 中去掉一些無關的輸出, 最后輸入如下:

