Java線程-守護線程與用戶線程

干java 開發(fā)這么多年, 之前一直沒留意java 進程還區(qū)分守護進程和用戶進程。守護進程這個概念最早還是在linux系統(tǒng)中接觸的,直到近期使用java開發(fā)心跳檢測功能時,使用Timer時才發(fā)現(xiàn)原來java也有守護線程的概念。

1. Java 線程

1.1 守護線程與用戶線程

Java 線程分為守護線程(DaemonThread) 和 用戶線程(UserThread)兩類.

通常情況下,我們使用Thread 創(chuàng)建的線程在默認情況下都屬于用戶線程, 當(dāng)在啟動線程之前, 執(zhí)行thread.setDaemon(true)時, 線程會變成守護線程。

其實在本質(zhì)上,用戶線程和守護線程并沒有太大區(qū)別,唯一的區(qū)別就是會影響虛擬機的退出(程序的終止)。當(dāng)jvm中只剩下守護線程時,虛擬機會退出,及程序終止;而當(dāng)jvm中至少擁有一個用戶線程時,jvm都不會退出。

1.2 守護線程特點

Java 中的守護線程和linux 中的守護進程還是有些區(qū)別的, linux 守護進程時系統(tǒng)級別的, 當(dāng)系統(tǒng)退出時, 才會終止. 而java 中的守護線程時jvm 級別的, 當(dāng)jvm中無任何用戶進程時, 守護進程銷毀, jvm 退出, 程序終止. 筆者認為java 守護進程的最主要的特點有:

守護進程是運行在程序后臺的線程

守護進程創(chuàng)建的進程,依然時守護進程

守護進程不會影響jvm的退出,當(dāng)jvm只剩余守護進程時,jvm 進行退出

守護進行在jvm退出時,自動銷毀

在開發(fā)java 守護線程時, 需要注意:

在線程啟動之前, 及執(zhí)行thread.start() 方法前, 設(shè)置thread.setDemon(true);

在守護線程中啟動的子線程也是守護線程

守護線程不建議進行寫操作, 因為守護進程隨時可能結(jié)束。

1.3 守護線程適用場景

針對于守護線程的特點,筆者認為,java 守護線程通??捎糜陂_發(fā)一些為其它用戶線程服務(wù)的功能。比如說心跳檢測,事件監(jiān)聽等。Java 中最有名的守護進程當(dāng)屬GC(垃圾回收)

2. java 守護線程開發(fā)

開發(fā)守護進程時需要注意兩點:

必須在線程啟動之前,即執(zhí)行thread.start()方法前, 執(zhí)行thread.setDaemon(true) 方法,否則會拋出異常IllegalThreadStateException

守護線程中創(chuàng)建的線程也是守護線程

2.1 測試程序退出

注釋thread.setDaemon(true)時, 線程為用戶線程, 程序進行無線循環(huán), 程序不終止。

設(shè)置thread.setDaemon(true)后, 線程變成守護線程, 程序直接終止, 僅輸出一行信息"main thread done"。 因為程序執(zhí)行完system 語句之后, main 程序作為唯一的一個用戶線程執(zhí)行結(jié)束了, jvm 中只剩下一個守護進程,所以jvm 便退出了。

public class TestThread {

? ? public static void main(String[] args) {

? ? ? ? AnsyTask ansyTask = new AnsyTask();

? ? ? ? Thread thread = new Thread(ansyTask);

? ? ? ? // 設(shè)置線程為異步線程

? ? ? ? // thread.setDaemon(true);

? ? ? ? // 啟動線程

? ? ? ? thread.start();


? ? ? ? System.out.println("main thread done");

? ? }

}

class AnsyTask implements Runnable{

? ? @Override

? ? public void run() {

? ? ? ? while (true){

? ? ? ? ? ? System.out.println(LocalDateTime.now() + "-hello,thread");

? ? ? ? }

? ? }

}

2.2 測試守護線程中創(chuàng)建新的線程

測試會發(fā)現(xiàn), 默認情況下, 守護線程創(chuàng)建的子線程依然是守護線程,用戶創(chuàng)建的守護線程依然時用戶線程。也可以在創(chuàng)建子線程時通過setDaemon()方法修改.

public class TestThread {

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

? ? ? ? AnsyTask ansyTask = new AnsyTask();

? ? ? ? Thread thread = new Thread(ansyTask);

? ? ? ? // 設(shè)置線程為異步線程

? ? ? ? thread.setDaemon(true);

? ? ? ? // 啟動線程

? ? ? ? thread.start();

? ? ? ? // 給守護線程點兒執(zhí)行時間

? ? ? ? Thread.sleep(1000l);

? ? }

}

class AnsyTask implements Runnable{

? ? @Override

? ? public void run() {

? ? ? ? Thread thread = new Thread("subThread");

? ? ? ? System.out.println(thread.getName() + " is daemon:" + thread.isDaemon());

? ? }

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容