java高并發(fā)系列-第9天:用戶線程和守護線程

守護線程是一種特殊的線程,在后臺默默地完成一些系統(tǒng)性的服務,比如垃圾回收線程JIT線程都是守護線程。與之對應的是用戶線程,用戶線程可以理解為是系統(tǒng)的工作線程,它會完成這個程序需要完成的業(yè)務操作。如果用戶線程全部結(jié)束了,意味著程序需要完成的業(yè)務操作已經(jīng)結(jié)束了,系統(tǒng)可以退出了。所以當系統(tǒng)只剩下守護進程的時候,java虛擬機會自動退出。

創(chuàng)新互聯(lián)建站專注于江城網(wǎng)站建設服務及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供江城營銷型網(wǎng)站建設,江城網(wǎng)站制作、江城網(wǎng)頁設計、江城網(wǎng)站官網(wǎng)定制、重慶小程序開發(fā)服務,打造江城網(wǎng)絡公司原創(chuàng)品牌,更為您提供江城網(wǎng)站排名全網(wǎng)營銷落地服務。

java線程分為用戶線程和守護線程,線程的daemon屬性為true表示是守護線程,false表示是用戶線程。

下面我們來看一下守護線程的一些特性。

程序只有守護線程時,系統(tǒng)會自動退出

package com.itsoku.chat03;

/**
 * 微信公眾號:javacode2018,獲取年薪50萬課程
 */
public class Demo1 {

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

        @Override
        public void run() {
            System.out.println(this.getName() + "開始執(zhí)行," + (this.isDaemon() ? "我是守護線程" : "我是用戶線程"));
            while (true) ;
        }
    }

    public static void main(String[] args) {
        T1 t1 = new T1("子線程1");
        t1.start();
        System.out.println("主線程結(jié)束");
    }
}

運行上面代碼,結(jié)果如下:

java高并發(fā)系列 - 第9天:用戶線程和守護線程

可以看到主線程已經(jīng)結(jié)束了,但是程序無法退出,原因:子線程1是用戶線程,內(nèi)部有個死循環(huán),一直處于運行狀態(tài),無法結(jié)束。

再看下面的代碼:

package com.itsoku.chat03;

/**
 * 微信公眾號:javacode2018,獲取年薪50萬課程
 */
public class Demo2 {

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

        @Override
        public void run() {
            System.out.println(this.getName() + "開始執(zhí)行," + (this.isDaemon() ? "我是守護線程" : "我是用戶線程"));
            while (true) ;
        }
    }

    public static void main(String[] args) {
        T1 t1 = new T1("子線程1");
        t1.setDaemon(true);
        t1.start();
        System.out.println("主線程結(jié)束");
    }
}

運行結(jié)果:

java高并發(fā)系列 - 第9天:用戶線程和守護線程

程序可以正常結(jié)束了,代碼中通過t1.setDaemon(true);將t1線程設置為守護線程,main方法所在的主線程執(zhí)行完畢之后,程序就退出了。

結(jié)論:當程序中所有的用戶線程執(zhí)行完畢之后,不管守護線程是否結(jié)束,系統(tǒng)都會自動退出。

設置守護線程,需要在start()方法之前進行

package com.itsoku.chat03;

import java.util.concurrent.TimeUnit;

/**
 * 微信公眾號:javacode2018,獲取年薪50萬課程
 */
public class Demo3 {

    public static void main(String[] args) {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                try {
                    TimeUnit.SECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t1.start();
        t1.setDaemon(true);
    }
}

t1.setDaemon(true);是在t1的start()方法之后執(zhí)行的,執(zhí)行會報異常,運行結(jié)果如下:

java高并發(fā)系列 - 第9天:用戶線程和守護線程

線程daemon的默認值

我們看一下創(chuàng)建線程源碼,位于Thread類的init()方法中:

Thread parent = currentThread();
this.daemon = parent.isDaemon();

dameon的默認值為為父線程的daemon,也就是說,父線程如果為用戶線程,子線程默認也是用戶現(xiàn)場,父線程如果是守護線程,子線程默認也是守護線程。

示例代碼:

package com.itsoku.chat03;

import java.util.concurrent.TimeUnit;

/**
 * 微信公眾號:javacode2018,獲取年薪50萬課程
 */
public class Demo4 {
    public static class T1 extends Thread {
        public T1(String name) {
            super(name);
        }

        @Override
        public void run() {
            System.out.println(this.getName() + ".daemon:" + this.isDaemon());
        }
    }

    public static void main(String[] args) throws InterruptedException {

        System.out.println(Thread.currentThread().getName() + ".daemon:" + Thread.currentThread().isDaemon());

        T1 t1 = new T1("t1");
        t1.start();

        Thread t2 = new Thread() {
            @Override
            public void run() {
                System.out.println(this.getName() + ".daemon:" + this.isDaemon());
                T1 t3 = new T1("t3");
                t3.start();
            }
        };

        t2.setName("t2");
        t2.setDaemon(true);
        t2.start();

        TimeUnit.SECONDS.sleep(2);
    }
}

運行代碼,輸出:

main.daemon:false
t1.daemon:false
t2.daemon:true
t3.daemon:true

t1是由主線程(main方法所在的線程)創(chuàng)建的,main線程是t1的父線程,所以t1.daemon為false,說明t1是用戶線程。

t2線程調(diào)用了setDaemon(true);將其設為守護線程,t3是由t2創(chuàng)建的,所以t3默認線程類型和t2一樣,t2.daemon為true。

總結(jié)

  1. java中的線程分為用戶線程守護線程
  2. 程序中的所有的用戶線程結(jié)束之后,不管守護線程處于什么狀態(tài),java虛擬機都會自動退出
  3. 調(diào)用線程的實例方法setDaemon()來設置線程是否是守護線程
  4. setDaemon()方法必須在線程的start()方法之前調(diào)用,在后面調(diào)用會報異常,并且不起效
  5. 線程的daemon默認值和其父線程一樣

java高并發(fā)系列連載中,總計估計會有四五十篇文章,可以關注公眾號:javacode2018,獲取最新文章。

java高并發(fā)系列 - 第9天:用戶線程和守護線程

本文名稱:java高并發(fā)系列-第9天:用戶線程和守護線程
分享網(wǎng)址:http://muchs.cn/article30/ihchpo.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設計公司、、用戶體驗網(wǎng)站導航、移動網(wǎng)站建設關鍵詞優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設計公司