高并發編程-Daemon Thread的創建以及使用場景分析
文章目錄
官方文檔
Daemon Thread VS User Thread
Daemon thread的特點
方法
void setDaemon(boolean status)
boolean isDaemon()
Exceptions in Daemon thread
例子
使用場景分析
官方文檔
我們以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.
1
2
3
4
5
6
7
此方法用于將當前線程標記為守護程序線程或用戶線程。
舉個例子:
如果有一個用戶線程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
1
2
3
4
5
此方法用于檢查當前是守護進程。 如果線程是守護進程,則返回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(); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
例子
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()); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
執行結果:
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)
舉個例子: 當A到B建立了一個長連接 ,長連接是需要發心跳的,維持這個連接。 這個時候可以在中開啟一個Daemon Thread用于心跳檢測,當A死掉的時候,這個Daemon Thread 也會被JVM終止掉,就避免了A和B之間已經斷開,但是心跳檢測可能報錯了但一直不退出的情況的發生。
JVM 任務調度
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。