最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中用戶線程與守護(hù)線程的使用區(qū)別

 更新時間:2022年05月19日 16:29:55   作者:??Java中文社群????  
這篇文章主要介紹了Java中用戶線程與守護(hù)線程的使用區(qū)別,Java語言中無論是線程還是線程池,默認(rèn)都是用戶線程,因此用戶線程也被成為普通線程,下文關(guān)于其與守護(hù)線程的區(qū)別詳情,需要的小伙伴可以參考一下

前言;

在 Java 語言中線程分為兩類:用戶線程和守護(hù)線程,而二者之間的區(qū)別卻鮮有人知,所以本文磊哥帶你來看二者之間的區(qū)別,以及守護(hù)線程需要注意的一些事項。

1.默認(rèn)用戶線程

Java 語言中無論是線程還是線程池,默認(rèn)都是用戶線程,因此用戶線程也被成為普通線程。

以線程為例,想要查看線程是否為守護(hù)線程只需通過調(diào)用 isDaemon() 方法查詢即可,如果查詢的值為 false 則表示不為守護(hù)線程,自然也就屬于用戶線程了,

如下代碼所示:

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("我是子線程");
        }
    });
    System.out.println("子線程==守護(hù)線程:" + thread.isDaemon());
    System.out.println("主線程==守護(hù)線程:" + Thread.currentThread().isDaemon());
}

以上程序的執(zhí)行結(jié)果為: 

 從上述結(jié)果可以看出,默認(rèn)情況下主線程和創(chuàng)建的新線程都為用戶線程。

PS:Thread.currentThread() 的意思是獲取執(zhí)行當(dāng)前代碼的線程實(shí)例。

2.主動修改為守護(hù)線程

守護(hù)線程(Daemon Thread)也被稱之為后臺線程或服務(wù)線程,守護(hù)線程是為用戶線程服務(wù)的,當(dāng)程序中的用戶線程全部執(zhí)行結(jié)束之后,守護(hù)線程也會跟隨結(jié)束。

守護(hù)線程的角色就像“服務(wù)員”,而用戶線程的角色就像“顧客”,當(dāng)“顧客”全部走了之后(全部執(zhí)行結(jié)束),那“服務(wù)員”(守護(hù)線程)也就沒有了存在的意義,所以當(dāng)一個程序中的全部用戶線程都結(jié)束執(zhí)行之后,那么無論守護(hù)線程是否還在工作都會隨著用戶線程一塊結(jié)束,整個程序也會隨之結(jié)束運(yùn)行。

那如何將默認(rèn)的用戶線程修改為守護(hù)線程呢?

這個問題要分為兩種情況來回答,首先如果是線程,則可以通過設(shè)置 setDaemon(true) 方法將用戶線程直接修改為守護(hù)線程,而如果是線程池則需要通過 ThreadFactory 將線程池中的每個線程都為守護(hù)線程才行,接下來我們分別來實(shí)現(xiàn)一下。

2.1 設(shè)置線程為守護(hù)線程

如果使用的是線程,可以通過 setDaemon(true) 方法將線程類型更改為守護(hù)線程,如下代碼所示:

 public static void main(String[] args) throws InterruptedException {
     Thread thread = new Thread(new Runnable() {
         @Override
         public void run() {
             System.out.println("我是子線程");
         }
     });
     // 設(shè)置子線程為守護(hù)線程
     thread.setDaemon(true);
     System.out.println("子線程==守護(hù)線程:" + thread.isDaemon());
     System.out.println("主線程==守護(hù)線程:" + Thread.currentThread().isDaemon());
 }

以上程序的執(zhí)行結(jié)果為: 

2.2 設(shè)置線程池為守護(hù)線程

要把線程池設(shè)置為守護(hù)線程相對來說麻煩一些,需要將線程池中的所有線程都設(shè)置成守護(hù)線程,這個時候就需要使用 ThreadFactory 來定義線程池中每個線程的線程類型了,具體實(shí)現(xiàn)代碼如下:

// 創(chuàng)建固定個數(shù)的線程池
ExecutorService threadPool = Executors.newFixedThreadPool(10, new ThreadFactory() {
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        // 設(shè)置線程為守護(hù)線程
        t.setDaemon(false);
        return t;
    }
});

如下圖所示: 

如上圖所示,可以看出,整個程序中有 10 個守護(hù)線程都是我創(chuàng)建的。其他幾種創(chuàng)建線程池的設(shè)置方式類似,都是通過 ThreadFactory 統(tǒng)一設(shè)置的,這里就不一一列舉了。

3.守護(hù)線程 VS 用戶線程

通過前面的學(xué)習(xí)我們可以創(chuàng)建兩種不同的線程類型了,那二者有什么差異呢?接下來我們使用一個小示例來看一下。

下面我們創(chuàng)建一個線程,分別將這個線程設(shè)置為用戶線程和守護(hù)線程,在每個線程中執(zhí)行一個 for 循環(huán),總共執(zhí)行 10 次信息打印,每次打印之后休眠 100 毫秒,來觀察程序的運(yùn)行結(jié)果。

3.1 用戶線程

新建的線程默認(rèn)就是用戶線程,因此我們無需對線程進(jìn)行任何特殊的處理,執(zhí)行 for 循環(huán)即可(總共執(zhí)行 10 次信息打印,每次打印之后休眠 100 毫秒),實(shí)現(xiàn)代碼如下:

/**
 * Author:Java中文社群
 */
public class DaemonExample {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 10; i++) {
                    // 打印 i 信息
                    System.out.println("i:" + i);
                    try {
                        // 休眠 100 毫秒
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        // 啟動線程
        thread.start();
    }
}

以上程序執(zhí)行結(jié)果如下: 

 從上述結(jié)果可以看出,當(dāng)程序執(zhí)行完 10 次打印之后才會正常結(jié)束進(jìn)程。

3.2 守護(hù)線程

/**
 * Author:Java中文社群
 */
public class DaemonExample {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 10; i++) {
                    // 打印 i 信息
                    System.out.println("i:" + i);
                    try {
                        // 休眠 100 毫秒
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        // 設(shè)置為守護(hù)線程
        thread.setDaemon(true);
        // 啟動線程
        thread.start();
    }
}

以上程序執(zhí)行結(jié)果如下: 

 從上述結(jié)果可以看出,當(dāng)線程設(shè)置為守護(hù)線程之后,整個程序不會等守護(hù)線程 for 循環(huán) 10 次之后再進(jìn)行關(guān)閉,而是當(dāng)主線程結(jié)束之后,守護(hù)線程只執(zhí)行了一次循環(huán)就結(jié)束運(yùn)行了,由此可以看出守護(hù)線程和用戶線程的不同。

3.3 小結(jié)

守護(hù)線程是為用戶線程服務(wù)的,當(dāng)一個程序中的所有用戶線程都執(zhí)行完成之后程序就會結(jié)束運(yùn)行,程序結(jié)束運(yùn)行時不會管守護(hù)線程是否正在運(yùn)行,由此我們可以看出守護(hù)線程在 Java 體系中權(quán)重是比較低的。

4.守護(hù)線程注意事項

守護(hù)線程的使用需要注意以下三個問題:

  • 守護(hù)線程的設(shè)置 setDaemon(true) 必須要放在線程的 start() 之前,否則程序會報錯。
  • 在守護(hù)線程中創(chuàng)建的所有子線程都是守護(hù)線程。
  • 使用 jojn() 方法會等待一個線程執(zhí)行完,無論此線程是用戶線程還是守護(hù)線程。

接下來我們分別演示一下,以上的注意事項。

4.1 setDaemon 執(zhí)行順序

當(dāng)我們將 setDaemon(true) 設(shè)置在 start() 之后,如下代碼所示:

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 1; i <= 10; i++) {
                // 打印 i 信息
                System.out.println("i:" + i + ",isDaemon:" +
                            Thread.currentThread().isDaemon());
                try {
                    // 休眠 100 毫秒
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });
    // 啟動線程
    thread.start();
    // 設(shè)置為守護(hù)線程
    thread.setDaemon(true);
}

以上程序執(zhí)行結(jié)果如下: 

 從上述結(jié)果可以看出,當(dāng)我們將 setDaemon(true) 設(shè)置在 start() 之后,不但程序的執(zhí)行會報錯,而且設(shè)置的守護(hù)線程也不會生效。

4.2 守護(hù)線程的子線程

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            Thread thread2 = new Thread(new Runnable() {
                @Override
                public void run() {

                }
            });
            System.out.println("守護(hù)線程的子線程 thread2 isDaemon:" +
                              thread2.isDaemon());
        }
    });
    // 設(shè)置為守護(hù)線程
    thread.setDaemon(true);
    // 啟動線程
    thread.start();

    Thread.sleep(1000);
}

以上程序執(zhí)行結(jié)果如下: 

 從上述結(jié)果可以看出,守護(hù)線程中創(chuàng)建的子線程,默認(rèn)情況下也屬于守護(hù)線程。

4.3 join 與守護(hù)線程

通過 3.2 部分的內(nèi)容我們可以看出,默認(rèn)情況下程序結(jié)束并不會等待守護(hù)線程執(zhí)行完,而當(dāng)我們調(diào)用線程的等待方法 join() 時,執(zhí)行的結(jié)果就會和 3.2 的結(jié)果有所不同,下面我們一起來看吧,

示例代碼如下:

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 1; i <= 10; i++) {
                // 打印 i 信息
                System.out.println("i:" + i);
                try {
                    // 休眠 100 毫秒
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });
    // 設(shè)置為守護(hù)線程
    thread.setDaemon(true);
    // 啟動線程
    thread.start();
    // 等待線程執(zhí)行完
    thread.join();
    System.out.println("子線程==守護(hù)線程:" + thread.isDaemon());
    System.out.println("主線程==守護(hù)線程:" + Thread.currentThread().isDaemon());
}

以上程序執(zhí)行結(jié)果如下: 

 通過上述結(jié)果我們可以看出,即使是守護(hù)線程,當(dāng)程序中調(diào)用 join() 方法時,程序依然會等待守護(hù)線程執(zhí)行完成之后再結(jié)束進(jìn)程。

5.守護(hù)線程應(yīng)用場景

守護(hù)線程的典型應(yīng)用場景就是垃圾回收線程,當(dāng)然還有一些場景也非常適合使用守護(hù)線程,比如服務(wù)器端的健康檢測功能,對于一個服務(wù)器來說健康檢測功能屬于非核心非主流的服務(wù)業(yè)務(wù),像這種為了主要業(yè)務(wù)服務(wù)的業(yè)務(wù)功能就非常合適使用守護(hù)線程,當(dāng)程序中的主要業(yè)務(wù)都執(zhí)行完成之后,服務(wù)業(yè)務(wù)也會跟隨者一起銷毀。

6.守護(hù)線程的執(zhí)行優(yōu)先級

首先來說,線程的類型(用戶線程或守護(hù)線程)并不影響線程執(zhí)行的優(yōu)先級,如下代碼所示,定義一個用戶線程和守護(hù)線程,分別執(zhí)行 10 萬次循環(huán),通過觀察最后的打印結(jié)果來確認(rèn)線程類型對程序執(zhí)行優(yōu)先級的影響。

public class DaemonExample {
    private static final int count = 100000;
    public static void main(String[] args) throws InterruptedException {
        // 定義任務(wù)
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < count; i++) {
                    System.out.println("執(zhí)行線程:" + Thread.currentThread().getName());
                }
            }
        };
        // 創(chuàng)建守護(hù)線程 t1
        Thread t1 = new Thread(runnable, "t1");
        // 設(shè)置為守護(hù)線程
        t1.setDaemon(true);
        // 啟動線程
        t1.start();
        // 創(chuàng)建用戶線程 t2
        Thread t2 = new Thread(runnable, "t2");
        // 啟動線程
        t2.start();
    }
}

以上程序執(zhí)行結(jié)果如下: 

 通過上述結(jié)果可以看出,線程的類型不管是守護(hù)線程還是用戶線程對程序執(zhí)行的優(yōu)先級是沒有任何影響的,而當(dāng)我們將 t2 的優(yōu)先級調(diào)整為最大時,整個程序的運(yùn)行結(jié)果就完全不同了,

如下代碼所示:

public class DaemonExample {
    private static final int count = 100000;
    public static void main(String[] args) throws InterruptedException {
        // 定義任務(wù)
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < count; i++) {
                    System.out.println("執(zhí)行線程:" + Thread.currentThread().getName());
                }
            }
        };
        // 創(chuàng)建守護(hù)線程 t1
        Thread t1 = new Thread(runnable, "t1");
        // 設(shè)置為守護(hù)線程
        t1.setDaemon(true);
        // 啟動線程
        t1.start();
        // 創(chuàng)建用戶線程 t2
        Thread t2 = new Thread(runnable, "t2");
        // 設(shè)置 t2 的優(yōu)先級為最高
        t2.setPriority(Thread.MAX_PRIORITY);
        // 啟動線程
        t2.start();
    }
}

以上程序執(zhí)行結(jié)果如下: 

00000000 通過上述的結(jié)果可以看出,程序的類型和程序執(zhí)行的優(yōu)先級是沒有任何關(guān)系,當(dāng)新創(chuàng)建的線程默認(rèn)的優(yōu)先級都是 5 時,無論是守護(hù)線程還是用戶線程,它們執(zhí)行的優(yōu)先級都是相同的,當(dāng)將二者的優(yōu)先級設(shè)置不同時,執(zhí)行的結(jié)果也會隨之改變(優(yōu)先級設(shè)置的越高,最早被執(zhí)行的概率也越大)。

7.總結(jié)

在 Java 語言中線程分為用戶線程和守護(hù)線程,守護(hù)線程是用來為用戶線程服務(wù)的,當(dāng)一個程序中的所有用戶線程都結(jié)束之后,無論守護(hù)線程是否在工作都會跟隨用戶線程一起結(jié)束。守護(hù)線程從業(yè)務(wù)邏輯層面來看權(quán)重比較低,但對于線程調(diào)度器來說無論是守護(hù)線程還是用戶線程,在優(yōu)先級相同的情況下被執(zhí)行的概率都是相同的。守護(hù)線程的經(jīng)典使用場景是垃圾回收線程,守護(hù)線程中創(chuàng)建的線程默認(rèn)情況下也都是守護(hù)線程。

到此這篇關(guān)于Java中用戶線程與守護(hù)線程的使用區(qū)別的文章就介紹到這了,更多相關(guān)Java線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringCloud中的服務(wù)接口(api)

    SpringCloud中的服務(wù)接口(api)

    這篇文章主要介紹了SpringCloud中的服務(wù)接口(api),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • InputStream數(shù)據(jù)結(jié)構(gòu)示例解析

    InputStream數(shù)據(jù)結(jié)構(gòu)示例解析

    這篇文章主要為大家介紹了InputStream數(shù)據(jù)結(jié)構(gòu)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • Spring指定bean在哪個應(yīng)用加載(示例詳解)

    Spring指定bean在哪個應(yīng)用加載(示例詳解)

    本文通過實(shí)例代碼介紹了Spring指定bean在哪個應(yīng)用加載,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-08-08
  • SpringMVC中的常用注解源碼及解析

    SpringMVC中的常用注解源碼及解析

    這篇文章主要介紹了SpringMVC中的常用注解源碼及解析,SpringMVC是一種基于Java的Web框架,它使用了許多注解來簡化開發(fā)過程,本文列舉了一些常用的注解,需要的朋友可以參考下
    2023-10-10
  • SpringBoot依賴和代碼分開打包的實(shí)現(xiàn)步驟

    SpringBoot依賴和代碼分開打包的實(shí)現(xiàn)步驟

    本文主要介紹了SpringBoot依賴和代碼分開打包的實(shí)現(xiàn)步驟,,這種方法將依賴和代碼分開打包,一般更新只有代碼修改,Pom文件是不會經(jīng)常改動的,感興趣的可以了解一下
    2023-10-10
  • Java編程之jdk1.4,jdk1.5和jdk1.6的區(qū)別分析(經(jīng)典)

    Java編程之jdk1.4,jdk1.5和jdk1.6的區(qū)別分析(經(jīng)典)

    這篇文章主要介紹了Java編程之jdk1.4,jdk1.5和jdk1.6的區(qū)別分析,結(jié)合實(shí)例形式較為詳細(xì)的分析說明了jdk1.4,jdk1.5和jdk1.6版本的使用區(qū)別,需要的朋友可以參考下
    2015-12-12
  • Mybatisplus詳解如何注入自定義的SQL

    Mybatisplus詳解如何注入自定義的SQL

    mybatis-plus 提供了許多默認(rèn)單表 CRUD 語句,對于其他 SQL 情況愛莫能助。如果有一個刪庫跑路,并且需要多次調(diào)用,來清空多張表數(shù)據(jù)得需求,那么如何把他封裝在 mybatis-plus 中調(diào)用呢,下面我們一起來看一下
    2022-06-06
  • 基于java內(nèi)部類作用的深入分析

    基于java內(nèi)部類作用的深入分析

    本篇文章介紹了,基于java內(nèi)部類作用的深入分析。需要的朋友參考下
    2013-05-05
  • 帶你入門Java的集合

    帶你入門Java的集合

    Java的集合類型都是對java.util包中Collection接口的繼承,這里我們主要介紹依賴于collection的一些主分支,一起來看一下Java中的collection集合類型總結(jié)
    2021-07-07
  • MyBatis-plus+達(dá)夢數(shù)據(jù)庫實(shí)現(xiàn)自動生成代碼的示例

    MyBatis-plus+達(dá)夢數(shù)據(jù)庫實(shí)現(xiàn)自動生成代碼的示例

    這篇文章主要介紹了MyBatis-plus+達(dá)夢數(shù)據(jù)庫實(shí)現(xiàn)自動生成代碼的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08

最新評論

永吉县| 金塔县| 佳木斯市| 翁源县| 临泽县| 丘北县| 台东县| 枞阳县| 东方市| 喀什市| 安陆市| 和静县| 西乌珠穆沁旗| 通榆县| 鹤山市| 石棉县| 台江县| 若羌县| 江孜县| 武山县| 汝州市| 尉氏县| 绍兴县| 青海省| 洪雅县| 九龙城区| 泽州县| 霍林郭勒市| 晋中市| 阿图什市| 宜兰县| 伊川县| 玛沁县| 南平市| 南投县| 桂阳县| 家居| 河池市| 恭城| 兰溪市| 城口县|