Java 多線程基礎(十一)線程優先級和守護線程

 Java 多線程基礎(十一)線程優先級和守護線程

一、線程優先級

Java 提供了一個線程調度器來監控程序啟動後進去就緒狀態的所有線程。線程調度器通過線程的優先級來決定調度哪些線程執行。一般來說,Java的線程調度器採用時間片輪轉算法使多個線程輪轉獲得CPU的時間片。然而根據實際情況,每個線程的重要程序也不相同,有時候我們想讓一些線程優先執行,那麼我們可以將他的優先級調高一下,這樣它們獲得的時間片會多一些。

多個線程處於就緒狀態時,若這些線程的優先級相同,則線程調度器會按時間片輪轉方式或獨佔方式來分配線程的執行時間。

java 中的線程優先級的範圍是1~10,默認的優先級是5。“高優先級線程”會優先於“低優先級線程”執行。

Java中線程優先級分為三個級別:

  • 低優先級:1~4,其中類變量 Thread.MIN_PRORITY 最低,數值為1;
  • 默認優先級:如果一個線程沒有指定優先級,默認優先級為5,由類變量 Thread.NORM_PRORITY表示;
  • 高優先級:6~10,類變量 Thread.MAX_PRORITY 最高,數值為10。

注意:具有相同優先級的多個線程,若它們都為高優先級Thread.MAX_PRORITY,則每個線程都是獨佔式的,也就是這些線程將被順序執行;若它們優先級不是高優先級,則這些線程將被同時執行,可以說是無序執行。

java 中有兩種線程:用戶線程和守護線程。可以通過 isDaemon() 方法來區別它們:如果返回 false,則說明該線程是“用戶線程”;否則就是“守護線程”。
用戶線程一般用戶執行用戶級任務,而守護線程也就是“後台線程”,一般用來執行後台任務。需要注意的是:Java虛擬機在“用戶線程”都結束後會後退出。

JDK中對用戶線程與守護線程的解釋:

每個線程都有一個優先級。“高優先級線程”會優先於“低優先級線程”執行。每個線程都可以被標記為一個守護進程或非守護進程。在一些運行的主線程中創建新的子線程時,
子線程的優先級被設置為等於“創建它的主線程的優先級”,當且僅當“創建它的主線程是守護線程”時“子線程才會是守護線程”。
當Java虛擬機啟動時,通常有一個單一的非守護線程(該線程通過是通過main()方法啟動)。JVM會一直運行直到下面的任意一個條件發生,JVM就會終止運行:
①、調用了exit()方法,並且exit()有權限被正常執行。 ②、所有的“非守護線程”都死了(即JVM中僅僅只有“守護線程”)。
每一個線程都被標記為“守護線程”或“用戶線程”。當只有守護線程運行時,JVM會自動退出。
 

二、線程優先級示例

public class Demo01 {
    private static Object obj = new Object();
    public static void main(String[] args) {
        
        Thread t1 = new ThreadA("t1");
        Thread t2 = new ThreadA("t2");
        
        t1.setPriority(1); // 設置優先級為1
        t2.setPriority(10);// 設置優先級為10
        
        t1.start();
        t2.start();
    }
}
class ThreadA extends Thread{
    public ThreadA(String name) {
        super(name);
    }
    public void run() {
        for(int i = 0;i < 3;i++)
            System.out.println(Thread.currentThread().getName() + " [ " 
                    + Thread.currentThread().getPriority() + " ] loop " + i);  
    }
}
// 運行結果
t1 [ 1 ] loop 0
t2 [ 10 ] loop 0
t2 [ 10 ] loop 1
t2 [ 10 ] loop 2
t1 [ 1 ] loop 1
t1 [ 1 ] loop 2

說明:

①、主線程main的優先級是5。
②、t1的優先級被設為1,而t2的優先級被設為10。cpu在執行t1和t2的時候,根據時間片輪循調度,所以能夠併發執行。

三、守護線程示例

public class Demo {
    public static void main(String[] args) {

        System.out.println(Thread.currentThread().getName()
                +" [ isDaemon = "+Thread.currentThread().isDaemon()+ " ]");
        Thread t1=new ThreadA("t1");    
        Thread t2=new MyDaemon("t2");    
        t2.setDaemon(true);// 設置t2為守護線程
        t1.start();                        
        t2.start();                        
    }
}
class ThreadA extends Thread{
    public ThreadA(String name) {
        super(name);
    }

    public void run(){
        try {
            for (int i=0; i<5; i++) {
                Thread.sleep(3);
                System.out.println(this.getName() +"[ isDaemon = "+this.isDaemon()+ " ] " + "loop " + i);
            }
        } catch (InterruptedException e) {
        }
    }
};

class MyDaemon extends Thread{
    public MyDaemon(String name) {
        super(name);
    }

    public void run(){
        try {
            for (int i=0; i<10000; i++) {
                Thread.sleep(1);
                System.out.println(this.getName() +"[ isDaemon = " + this.isDaemon() +  " ] " +"loop "+i);
            }
        } catch (InterruptedException e) {
        }
    }
}
// 運行結果
main [ isDaemon = false ]
t2[ isDaemon = true ] loop 0
t2[ isDaemon = true ] loop 1
t2[ isDaemon = true ] loop 2
t1[ isDaemon = false ] loop 0
t2[ isDaemon = true ] loop 3
t2[ isDaemon = true ] loop 4
t1[ isDaemon = false ] loop 1
t2[ isDaemon = true ] loop 5
t2[ isDaemon = true ] loop 6
t2[ isDaemon = true ] loop 7
t1[ isDaemon = false ] loop 2
t2[ isDaemon = true ] loop 8
t2[ isDaemon = true ] loop 9
t2[ isDaemon = true ] loop 10
t1[ isDaemon = false ] loop 3
t2[ isDaemon = true ] loop 11
t2[ isDaemon = true ] loop 12
t2[ isDaemon = true ] loop 13
t2[ isDaemon = true ] loop 14
t1[ isDaemon = false ] loop 4
t2[ isDaemon = true ] loop 15

說明:

①、主線程main是用戶線程,它創建的子線程t1也是用戶線程。
②、t2 是守護線程。在“主線程main”和“子線程t1”(它們都是用戶線程)執行完畢,只剩t2這個守護線程的時候,JVM自動退出。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

您可能也會喜歡…