Java中的守护线程和非守护线程(转载)
<什么是守護線程,什么是非守護線程>
Java有兩種Thread:“守護線程Daemon”(守護線程)與“用戶線程User”(非守護線程)。
用戶線程:非守護線程包括常規(guī)的用戶線程或諸如用于處理GUI事件的事件調(diào)度線程,Java虛擬機在它所有非守護線程已經(jīng)離開后自動離開。
守護線程:守護線程則是用來服務(wù)用戶線程的,比如說GC線程。如果沒有其他用戶線程在運行,那么就沒有可服務(wù)對象,也就沒有理由繼續(xù)下去。(操作系統(tǒng)里面是沒有所謂的守護線程的概念,只有守護進程一說,但是Java語言機制是構(gòu)建在JVM的基礎(chǔ)之上的,意思是Java平臺把操作系統(tǒng)的底層給屏蔽起來,所以它可以在它自己的虛擬的平臺里面構(gòu)造出對 自己有利的機制,而語言或者說平臺的設(shè)計者多多少少是受到Unix思想的影響,而守護線程機制又是對JVM這樣的平臺湊合,于是守護線程應(yīng)運而生);
守護線程使用的情況較少,但并非無用,舉例來說,JVM的垃圾回收、內(nèi)存管理等線程都是守護線程。還有就是在做數(shù)據(jù)庫應(yīng)用時候,使用的數(shù)據(jù)庫連接池,連接池本身也包含著很多后臺線程,監(jiān)控連接個數(shù)、超時時間、狀態(tài)等等。
守護線程與用戶線程的唯一區(qū)別是:其實User Thread線程和Daemon Thread守護線程本質(zhì)上來說去沒啥區(qū)別的,唯一的區(qū)別之處就在虛擬機的離開,當JVM中所有的線程都是守護線程的時候,JVM就可以退出了(如果User Thread全部撤離,那么Daemon Thread也就沒啥線程好服務(wù)的了,所以虛擬機也就退出了);如果還有一個或以上的非守護線程則不會退出。(以上是針對正常退出,調(diào)用System.exit則必定會退出)。
舉個例子:就像天上人間的保安?(守護線程),里面有牌位姑娘(非守護線程),他們是可以同時干著各自的活兒,但是 姑娘們要是都被JC帶走了,那么門口的保安也就沒有存在的意義了。
?
<怎樣創(chuàng)建守護線程>
守護線程與普通線程寫法上基本沒什么區(qū)別,調(diào)用線程對象的方法setDaemon(true),則可以將其設(shè)置為守護線程。?? ??? 1、thread.setDaemon(true)必須在thread.start()之前設(shè)置,你不能把正在運行的常規(guī)線程設(shè)置為守護線程,否則會跑出一個IllegalThreadStateException異常,如果線程是守護線程,則isDaemon方法返回true。(備注:這點與守護進程有著明顯的區(qū)別,守護進程是創(chuàng)建后,讓進程擺脫原會話的控制+讓進程擺脫原進程組的控制+讓進程擺脫原控制終端的控制;所以說寄托于虛擬機的語言機制跟系統(tǒng)級語言有著本質(zhì)上面的區(qū)別)。
?????? 2、在Daemon線程中產(chǎn)生的新線程也是Daemon的。??(這一點又是有著本質(zhì)的區(qū)別了:守護進程fork()出來的子進程不再是守護進程,盡管它把父進程的進程相關(guān)信息復(fù)制過去了,但是子進程的進程的父進程不是init進程,所謂的守護進程本質(zhì)上說就是“父進程掛掉,init收養(yǎng),然后文件0,1,2都是/dev/null,當前目錄到/”)?
?????? 3、不是所有的應(yīng)用都可以分配給Daemon線程來進行服務(wù),比如讀寫操作或者計算邏輯。因為在Daemon Thread還沒來的及進行操作時,虛擬機可能已經(jīng)退出了。?
setDaemon方法的詳細說明:
?
<守護線程調(diào)度示例>
//示例1:完成文件輸出的守護線程任務(wù) import java.io.*; public class TestDemo { public static void main(String[] args) throws InterruptedException { Runnable tr = new TestRunnable(); Thread thread = new Thread(tr); thread.setDaemon(true); //設(shè)置守護線程 thread.start(); //開始執(zhí)行分進程 } class TestRunnable implements Runnable{ public void run(){ try{ Thread.sleep(1000);//守護線程阻塞1秒后運行 File f=new File("daemon.txt"); FileOutputStream os=new FileOutputStream(f,true); os.write("daemon".getBytes()); } catch(IOException e1){ e1.printStackTrace(); } catch(InterruptedException e2){ e2.printStackTrace(); } } } }?
運行結(jié)果:文件daemon.txt中沒有"daemon"字符串。
但是如果把thread.setDaemon(true); //設(shè)置守護線程注釋掉,文件daemon.txt是可以被寫入daemon字符串的
JRE判斷程序是否執(zhí)行結(jié)束的標準是所有的前臺執(zhí)線程行完畢了,而不管后臺線程的狀態(tài),因此,在使用后臺線程候一定要注意這個問題。
?
//示例2:線程的調(diào)度-守護線程?
public class Test { public static void main(String[] args) { Thread t1 = new MyCommon(); Thread t2 = new Thread( new MyDaemon()); t2.setDaemon( true); //設(shè)置為守護線程 t2.start(); t1.start(); } } class MyCommon extends Thread { public void run() { for ( int i = 0; i < 5; i++) { System.out.println( "線程1第" + i + "次執(zhí)行!"); try { Thread.sleep(7); } catch (InterruptedException e) { e.printStackTrace(); } } } } class MyDaemon implements Runnable { public void run() { for ( long i = 0; i < 9999999L; i++) { System.out.println( "后臺線程第" + i + "次執(zhí)行!"); try { Thread.sleep(7); } catch (InterruptedException e) { e.printStackTrace(); } } } } 運行結(jié)果: /*********************************** 后臺線程第0次執(zhí)行!??線程1第0次執(zhí)行!??
線程1第1次執(zhí)行!??
后臺線程第1次執(zhí)行!??
后臺線程第2次執(zhí)行!??
線程1第2次執(zhí)行!??
線程1第3次執(zhí)行!??
后臺線程第3次執(zhí)行!??
線程1第4次執(zhí)行!??
后臺線程第4次執(zhí)行!??
后臺線程第5次執(zhí)行!??
后臺線程第6次執(zhí)行!??
后臺線程第7次執(zhí)行!??
Process finished with exit code 0 **********************************/ 從上面的執(zhí)行結(jié)果可以看出: 前臺線程是保證執(zhí)行完畢的,后臺線程還沒有執(zhí)行完畢就退出了(當前線程全是守護線程時,JVM將退出)。 --------------------------------------------------------------------------------------- 注:本文轉(zhuǎn)載于:http://blog.csdn.net/wjh5240313226/article/details/51501941,感謝原文作者。
轉(zhuǎn)載于:https://www.cnblogs.com/GISQZC/p/5946189.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的Java中的守护线程和非守护线程(转载)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于.c和.h 和定义变量的问题
- 下一篇: 项目微管理 - 总结也是新的开始