Java 多線程(二)之 Thread 優先級


@

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 中, 線程的優先級有如下特點:

  1. Java 線程的優先級從 1~10;
  2. Java 線程默認優先級是 5;
  3. 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() 中去掉一些無關的輸出, 最后輸入如下:

繼承優先級


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM