天天看點

[改善Java代碼]線程優先級隻使用三個等級

線程的優先級(priority)決定了線程獲得CPU運作的機會,優先級越高獲得的運作機會越大,優先級越低獲得的機會越小.Java的線程有10個級别(準确的說是11個級别,級别為0的線程是JVM,應用程式不能設定該級别)

那是不是級别為10的線程肯定比級别為9的線程優先運作呢?

看代碼:

1 public class Client {
 2     public static void main(String[] args){
 3         //啟動20個不同優先級的線程
 4         for (int i = 0; i < 20; i++) {
 5             new TestThread().start(i % 10 + 1);
 6         }
 7 
 8     }
 9 }
10 
11 class TestThread implements Runnable {
12     //啟動線程
13     public void start(int _priority) {
14         Thread t = new Thread(this);
15         //設定線程優先級
16         t.setPriority(_priority);
17         t.start();
18     }
19 
20     @Override
21     public void run() {
22         //消耗CPU的計算,性能差的機器,請修改循環限制
23         for (int i = 0; i < 100000; i++) {
24             Math.hypot(Math.pow(924526789,i),Math.cos(i));
25         }
26         //輸出線程優先級
27         System.out.println("Priority:" + Thread.currentThread().getPriority());
28 
29     }
30 }      

該多線程類實作了Runnable接口,實作了run方法,注意在run方法中有一個比較占用CPU的計算,該計算毫無意義,隻是為了保證一個線程盡可能多的消耗CPU資源,目的是為了觀察在CPU繁忙時,不同優先級線程的執行順序.

需要說明的是,如果此處使用了Thread.sleep()方法,則不能展現出線程優先級的本質了,因為CPU并不繁忙,線程排程不會遵循優先級順序來進行排程.

上面代碼建立了20個線程,每個線程在運作時都耗盡了CPU資源,因為優先級不同,線程排程應該最先處理優先級最高的,然後處理優先級最低的,也就是先執行了2個優先級為10的線程,然後執行2個優先級為9的線程,2個優先級為8的線程....是結果并不是這樣的...

運作結果:

Priority:10
Priority:7
Priority:1
Priority:8
Priority:3
Priority:6
Priority:3
Priority:2
Priority:4
Priority:8
Priority:9
Priority:9
Priority:10
Priority:2
Priority:6
Priority:7
Priority:5
Priority:5
Priority:4
Priority:1      

println方法雖然有輸出損耗,可能會影響到輸出結果,但是不管運作多少次,都有兩個不争的事實.

(1)并不是嚴格遵守線程優先級别來執行的.

  因為優先級隻是代表獲得CPU運作的機會,并不代表強制的排序号.

(2)優先級差别越大,運作機會差别越明顯. 

  比如優先級為10的線程通常比優先級為2的線程先執行,但是優先級為6的線程和優先級為5的線程差别就不太明顯了.

這連個現象是優先級的一個重要表現:

因為線程運作是要獲得CPU資源的,誰能決定哪個線程先獲得哪個線程後獲得呢?

這是依照作業系統設定的線程優先級來配置設定的,每個線程需要運作,需要作業系統配置設定優先級和CPU資源,對Java來說,JVM調用作業系統的接口設定優先級,比如Windows作業系統是通過調用SetThreadPriority函數來設定的.

不同的作業系統線程的優先級是不相同的,Windows7個優先級,Linux有140個優先級,Freebsd則有255個(此處指的是優先級總數,不同作業系統有不同的分類,如中斷線程,作業系統等級等,各個作業系統具體使用者可用的線程數量也不相同).

Java是跨平台的系統,需要把10個優先級映射成不同作業系統的優先級,于是界定了Java的優先級隻是代表搶占CPU的機會大小,優先級越高,搶占CPU的機會越大.被執行的可能性越高.

Java的締造者們也發現了這個問題,于是在Thread類中設定了三個優先級,建議使用優先級常量,而不是1到10的随機數字.

public class Thread implements Runnable {
    /**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;
}      

建議使用這三個級别,不建議使用其他7個數字.

如果優先級相同,怎麼辦?

這也是由作業系統決定的,基本上是按照FIFO的原則,但是也不能完全保證.

作者:SummerChill