Java守護進程學習筆記
1.概述
Java的線程機制,在Java中有兩類線程:User Thread(用戶線程)、Daemon Thread(守護線程)。
Daemon的作用是為其他線程的運行提供服務,比如說GC線程。其實User Thread線程和Daemon Thread守護線程本質上來說去沒啥區(qū)別的,唯一的區(qū)別之處就在虛擬機的離開時候:如果User Thread全部撤離,那么Daemon Thread也就沒啥線程好服務的了,所以虛擬機也就退出了。只要當前JVM實例中尚存在任何一個非守護線程沒有結束,守護線程就全部工作;只有當最后一個非守護線程結束時,守護線程隨著JVM一同結束工作。守護線程最典型的應用就是 GC (垃圾回收器)。
1.1.注意點
public final void setDaemon(boolean on) ;但是有幾點需要注意:
1)、thread.setDaemon(true)必須在thread.start()之前設置,否則會跑出一個IllegalThreadStateException異常。你不能把正在運行的常規(guī)線程設置為守護線程。 (備注:這點與守護進程有著明顯的區(qū)別,守護進程是創(chuàng)建后,讓進程擺脫原會話的控制+讓進程擺脫原進程組的控制+讓進程擺脫原控制終端的控制;所以說寄托于虛擬機的語言機制跟系統(tǒng)級語言有著本質上面的區(qū)別)
2)、 在Daemon線程中產(chǎn)生的新線程也是Daemon的。 (這一點又是與守護線程有著本質的區(qū)別了:
守護進程fork()出來的子進程不再是守護進程,盡管它把父進程的進程相關信息復制過去了,但是子進程的進程的父進程不是init進程,所謂的守護進程本質上說就是“父進程掛掉,init收養(yǎng),然后文件0,1,2都是/dev/null,當前目錄到/”)
3)、不是所有的應用都可以分配給Daemon線程來進行服務,比如讀寫操作或者計算邏輯。因為在Daemon Thread還沒來的及進行操作時,虛擬機可能已經(jīng)退出了。
1.2.應用場景
但是daemon Thread實際應用在那里呢?舉個例子,web服務器中的Servlet,容器啟動時后臺初始化一個服務線程,即調度線程,負責處理http請求,然后每個請求過來調度線程從線程池中取出一個工作者線程來處理該請求,從而實現(xiàn)并發(fā)控制的目的。
2.實例
2.1.用戶線程提前結束
沒法守護了
2.1.1.代碼
package com.tech.ability.resume;
import com.tech.ability.util.DateUtil;
import com.tech.ability.util.SleepUtil;
/**
- Created by kikop on 2019/6/11.
*/
public class DaemonTest {
/**
* 守護進程
*/
static class MyDamonRunner implements Runnable{
@Override
public void run() {
try{
System.out.println(DateUtil.getCurrentThreadInfo("begin..."));
SleepUtil.second(10);
} finally {
System.out.println(DateUtil.getCurrentThreadInfo("finally run!"));
}
}
}
/**
* 普通進程
*/
static class MyNormalRunner implements Runnable{
@Override
public void run() {
try{
System.out.println(DateUtil.getCurrentThreadInfo("begin..."));
SleepUtil.second(5);
} finally {
System.out.println(DateUtil.getCurrentThreadInfo("finally run!"));
}
}
}
/**
* main普通進程
* @param args
*/
public static void main(String[] args) {
Thread normalThread=new Thread(new MyNormalRunner(),"normalThread");
normalThread.start();
Thread daemonThread=new Thread(new MyDamonRunner(),"daemonThread");
daemonThread.setDaemon(true);
daemonThread.start();
}
}
2.1.2.輸出結果
[2019-06-11 07:14:22] daemonThread-00012:begin...
[2019-06-11 07:14:22] normalThread-00011:begin...
[2019-06-11 07:14:27] normalThread-00011:finally run!
2.2.Daemon線程提前結束
2.2.1.代碼
package com.tech.ability.resume;
import com.tech.ability.util.DateUtil;
import com.tech.ability.util.SleepUtil;
/**
- Created by kikop on 2019/6/11.
*/
public class DaemonTest {
/**
* 守護進程
*/
static class MyDamonRunner implements Runnable{
@Override
public void run() {
try{
System.out.println(DateUtil.getCurrentThreadInfo("begin..."));
SleepUtil.second(10); //守護線程阻塞
File f = new File("daemon.txt");
FileOutputStream os = new FileOutputStream(f, true);
os.write("daemon".getBytes());
} finally {
System.out.println(DateUtil.getCurrentThreadInfo("finally run!"));
}
}
}
/**
* 普通進程
*/
static class MyNormalRunner implements Runnable{
@Override
public void run() {
try{
System.out.println(DateUtil.getCurrentThreadInfo("begin..."));
SleepUtil.second(15);
} finally {
System.out.println(DateUtil.getCurrentThreadInfo("finally run!"));
}
}
}
/**
* main普通進程
* @param args
*/
public static void main(String[] args) {
Thread normalThread=new Thread(new MyNormalRunner(),"normalThread");
normalThread.start();
Thread daemonThread=new Thread(new MyDamonRunner(),"daemonThread");
daemonThread.setDaemon(true);
daemonThread.start();
}
}
2.2.2.輸出結果
[2019-06-11 07:21:56] normalThread-00011:begin...
[2019-06-11 07:21:56] daemonThread-00012:begin...
[2019-06-11 07:22:07] daemonThread-00012:finally run!
[2019-06-11 07:22:12] normalThread-00011:finally run!
參考
1.java的守護進程與非守護進程
<u>https://blog.csdn.net/weixin_37766296/article/details/80404503</u>