文章目錄
- 官方文檔
- Daemon Thread VS User Thread
- Daemon thread的特點
- 方法
- void setDaemon(boolean status)
- boolean isDaemon()
- Exceptions in Daemon thread
- 例子
- 使用場景分析
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CO4QjNxczM1ETZiFjZ5U2YxYzX5MTMxQTMxMzLcJTMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
官方文檔
我們以JAVA8的doc為例 戳這裡
Daemon Thread VS User Thread
Java提供兩種類型的線程:使用者線程和守護程式線程。
- 使用者線程是高優先級線程。JVM将在終止任務之前等待任何使用者線程完成其任務。
- 守護程式線程是低優先級線程,其唯一作用是為使用者線程提供服務。
由于守護程式線程旨在為使用者線程提供服務,并且僅在使用者線程運作時才需要,是以一旦所有使用者線程完成執行,它們都不會阻止JVM退出。
這也就是為什麼通常存在于守護程式線程中的無限循環不會導緻問題,因為任何代碼(包括finally塊)都不會在所有使用者線程完成執行後執行。是以,不建議将守護程式線程用于I / O任務。
但是,這條規則有例外。守護程式線程中設計糟糕的代碼可能會阻止JVM退出。例如,在正在運作的守護程式線程上調用Thread.join()可以阻止應用程式的關閉。
Daemon thread的特點
- 當所有使用者線程完成執行時,它們無法阻止JVM退出。
- 當所有使用者線程完成執行時,JVM會自行終止
- 如果JVM發現正在運作的守護程式線程,它将終止該線程并在該關閉後自行終。 JVM不關心守護程式線程是否正在運作。
- 這是一個極低優先級的線程。
方法
void setDaemon(boolean status)
public final void setDaemon(boolean on)
parameters:
on : if true, marks this thread as a daemon thread.
exceptions:
IllegalThreadStateException: if only this thread is active.
SecurityException: if the current thread cannot modify this thread.
此方法用于将目前線程标記為守護程式線程或使用者線程。
舉個例子:
如果有一個使用者線程tU,那麼tU.setDaemon(true)會使它成為守護程式線程
如果有一個守護程式線程tD,那麼通過調用tD.setDaemon(false)會使它成為使用者線程。
boolean isDaemon()
public final boolean isDaemon()
returns:
This method returns true if this thread is a daemon thread;
false otherwise
此方法用于檢查目前是守護程序。 如果線程是守護程序,則傳回true,否則傳回false。
Exceptions in Daemon thread
如果在啟動線程後調用
setDaemon()
方法,則會抛出IllegalThreadStateException。
package com.artisan.test;
public class DaemonThread extends Thread {
public void run()
{
System.out.println("Thread name: " + Thread.currentThread().getName());
System.out.println("Check if its DaemonThread: "
+ Thread.currentThread().isDaemon());
}
public static void main(String[] args)
{
DaemonThread t1 = new DaemonThread();
DaemonThread t2 = new DaemonThread();
t1.start();
// Exception as the thread is already started
t1.setDaemon(true);
t2.start();
}
}
例子
package com.artisan.test;
import java.time.LocalDateTime;
public class DaemonThread extends Thread {
public DaemonThread(String name) {
super(name);
}
@Override
public void run() {
// Checking whether the thread is Daemon or not
if (Thread.currentThread().isDaemon()) {
try {
System.out.println(getName() + " is Daemon thread : running " + LocalDateTime.now());
// 休眠200s
Thread.sleep(200_000);
System.out.println(getName() + " is Daemon thread: over " + LocalDateTime.now());
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
try {
System.out.println(getName() + " is User thread : running " + LocalDateTime.now());
// 休眠5s
Thread.sleep(5_000);
System.out.println(getName() + " is User thread : over " + LocalDateTime.now());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName() + ": running " + LocalDateTime.now());
DaemonThread t1 = new DaemonThread("t1");
DaemonThread t2 = new DaemonThread("t2");
DaemonThread t3 = new DaemonThread("t3");
// Setting user thread t1 to Daemon
t1.setDaemon(true);
// starting first 2 threads
t1.start();
t2.start();
// Setting user thread t3 to Daemon
t3.setDaemon(true);
t3.start();
System.out.println(Thread.currentThread().getName() + ": over " + LocalDateTime.now());
}
}
執行結果:
- setDaemon(true) 設定為Daemon Thread
- JVM将在終止任務之前等待任何使用者線程完成其任務,JVM不關心守護程式線程是否正在運作,當使用者線程結束後将退出。 從日志中我們可以看到t2是個user thread ,休眠了5秒,t3是daemon thread 休眠200秒,但是我們看到t2 使用者線程執行完成後,jvm就退出了,雖然t3 daemon thread 還在進行中,這個時候t3已經被終止了。
使用場景分析
心跳檢測
A ----------------------------------------------------------------------------- B
–>Daemon Thread(Health Check)