當我們在Java中創建線程的時候,這個線程在默認的情況下是一個用戶線程,並且,如果這個線程在運行,那麼JVM就不會終結這個應用。和用戶線程不同,當一個線程被標記爲守護線程的時候,JVM在用戶線程結束的時候,是不會持續等待守護線程結束的,而是直接結束程序,並且結束程序中相關的守護線程。
Thread.setDaemon(true)
方法可以用來將線程置爲守護線程,參考下面的例子:
package com.sapphire.threads;
public class JavaDaemonThread {
public static void main(String[] args) throws InterruptedException {
Thread dt = new Thread(new DaemonThread(), "dt");
dt.setDaemon(true);
dt.start();
//continue program
Thread.sleep(30000);
System.out.println("Finishing program");
}
}
class DaemonThread implements Runnable{
@Override
public void run() {
while(true){
processSomething();
}
}
private void processSomething() {
try {
System.out.println("Processing daemon thread");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
當執行上面的程序時,JVM會包含main方法這個線程,而後在main方法中創建一個用戶線程,然後是變成了守護線程。當main函數結束的時候,程序就會結束,而且JVM也會同時關閉掉守護線程。
程序的輸出如下:
Processing daemon thread
Processing daemon thread
Processing daemon thread
Processing daemon thread
Processing daemon thread
Processing daemon thread
Finishing program
但是,如果我們沒有將線程置爲守護線程的話,程序就永遠都不會結束,就算main函數的線程執行完畢,程序仍然會繼續下去。
通常來說,我們創建一個守護線程爲了一些跟系統不那麼相關的功能。舉例來說,日誌線程或者監控系統資源狀態的線程等。
守護線程的配置必須在線程啓動之前,參考Javadoc
/** * Marks this thread as either a {@linkplain #isDaemon daemon} thread * or a user thread. The Java Virtual Machine exits when the only * threads running are all daemon threads. * * <p> This method must be invoked before the thread is started. * * @param on * if {@code true}, marks this thread as a daemon thread * * @throws IllegalThreadStateException * if this thread is {@linkplain #isAlive alive} * * @throws SecurityException * if {@link #checkAccess} determines that the current * thread cannot modify this thread */ public final void setDaemon(boolean on) { checkAccess(); if (isAlive()) { throw new IllegalThreadStateException(); } daemon = on; }