当所有非守护进行(Daemon Thread)都结束时,包括main线程,虚拟机会立即退出,即使守护线程含有finally,而且守护线程此时程序逻辑还没有执行到finally语句块,则会放弃执行finally语句块,所有守护线程都结束。
public class DaemonTest {
public static class DaemonRunner implements Runnable{
private long sleepTimeMills = 0;
DaemonRunner(long time){
sleepTimeMills = time;
}
public void run() {
try{
System.out.println("睡眠中");
Thread.sleep(sleepTimeMills);
}catch(InterruptedException e){
System.out.println("睡眠时中断发生");
}
finally{
System.out.println("finally模块被执行");
}
}
}
public static void main(String[] args) throws Exception{
Thread thread = new Thread(new DaemonRunner(1000),"DaemonThread");
thread.setDaemon(true);
thread.start();
//Thread.sleep(1000);
Thread.sleep(999);
System.out.println("main Thread is stop");
}
/*
* output1 main thread sleep 999 mills:
*
* 睡眠中
* main Thread is stop
*
* Process finished with exit code 0
* */
/* output2 main thread sleep 1000 mills:
*
* 睡眠中
* finally模块被执行
* main Thread is stop
*
* Process finished with exit code 0
* */
}
总结
- 直到所有非守护线程最后一条语句的结束之前,守护线程和其他线程一样会按照并行逻辑正常执行,但是当所有非守护线程结束时,守护线程的所有没有来得及执行的逻辑代码都放弃执行(包括catch模块和finally模块)
- 可能发生的情况,当main线程和守护线程睡眠的时间相等或者相差很短的时间,而且逻辑代码比较简单的情况下(如上述示例代码一样),这两种线程是有可能同时执行完的,或则main线程最后执行完;当然代码逻辑如果比较复杂,则可能发生的情况会更多
- 对于示例:两个线程只是相差1毫秒,但是执行的结果却不同。分4种情况:(1):main线程睡眠的时间小于Daemon线程的睡眠时间,而且main线程的代码逻辑非常简单,则很有可能mian线程执行完,Daemon线程都没有执行完;(2): main线程睡眠的时间小于Daemon线程的睡眠时间,而且main线程的代码逻辑比较复杂,则Daemon线程有可能正常退出,也可能被虚拟机终止,取决于代码相对复杂度;(3): main线程睡眠的时间大于Daemon线程的睡眠时间,而且Daemon线程的代码逻辑比较简单,则很有可能Daemon线程正常先于main线程执行完; (4): main线程睡眠的时间大于Daemon线程的睡眠时间,而且Daemon线程的代码逻辑比较复杂,则Daemon线程有可能正常退出,也可能被虚拟机终止,取决于代码相对复杂度;
- 因此不能在守护线程中的finally语句块中执行关闭资源的操作,很可能操作失败。