關於java線程的daemon的認識


在 JAVA中的CountDownLatch、CyclicBarrier、Semaphore的簡單測試 這文章里說到了線程的daemon問題,特寫一篇來分析一下。

上代碼:

 1 package com.yzl.dubbo;
 2 
 3 import java.util.concurrent.TimeUnit;
 4 
 5 /**
 6  * java Thread的daemon屬性測試
 7  * 結論:
 8  *       1、當虛擬機不存在daemon==false的線程時,虛擬機將會自動退出
 9  *    2、當虛擬機退出時,daemon里的finally代碼不一定會執行完全(可能執行到一半就被強制干掉了)
10  * @author yangzhilong
11  *
12  */
13 public class Daemon {
14 
15     public static void main(String[] args) {
16         Thread thread = new Thread(new DaemonRunner(), "daemon");
17         //當虛擬機不存在daemon==false的線程時,虛擬機將會自動退出
18         //mian線程屬於false
19         //不對這個屬性進行設置的線程也是false
20 //        thread.setDaemon(false);
21         thread.setDaemon(true);
22         thread.start();
23     }
24 
25     static class DaemonRunner implements Runnable {
26          @Override
27         public void run() {
28             for (int i = 0; i < 10; i++) {
29                 try {
30                     System.out.println("run ........");
31                     TimeUnit.SECONDS.sleep(5);
32                     System.out.println("end run......");
33                 } catch (Exception e) {
34                 } finally {
35                     System.out.println("finally is runing。。。。");
36                 }
37             }
38         }
39     }
40 }

注釋掉20行,放開21行的運行結果如下:

run ........

注釋掉21行,放開20行的運行結果如下:

run ........
end run......
finally is runing。。。。
run ........
end run......
finally is runing。。。。
run ........
end run......
finally is runing。。。。
run ........
end run......
finally is runing。。。。
run ........
end run......
finally is runing。。。。
run ........
end run......
finally is runing。。。。
run ........
end run......
finally is runing。。。。
run ........
end run......
finally is runing。。。。
run ........
end run......
finally is runing。。。。
run ........
end run......
finally is runing。。。。

我們來看看Thread的構造函數里的核心源碼:

 1 private void init(ThreadGroup g, Runnable target, String name,
 2                       long stackSize, AccessControlContext acc) {
 3         if (name == null) {
 4             throw new NullPointerException("name cannot be null");
 5         }
 6 
 7         this.name = name;
 8 
 9         Thread parent = currentThread();
10         SecurityManager security = System.getSecurityManager();
11         if (g == null) {
12             /* Determine if it's an applet or not */
13 
14             /* If there is a security manager, ask the security manager
15                what to do. */
16             if (security != null) {
17                 g = security.getThreadGroup();
18             }
19 
20             /* If the security doesn't have a strong opinion of the matter
21                use the parent thread group. */
22             if (g == null) {
23                 g = parent.getThreadGroup();
24             }
25         }
26 
27         /* checkAccess regardless of whether or not threadgroup is
28            explicitly passed in. */
29         g.checkAccess();
30 
31         /*
32          * Do we have the required permissions?
33          */
34         if (security != null) {
35             if (isCCLOverridden(getClass())) {
36                 security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
37             }
38         }
39 
40         g.addUnstarted();
41 
42         this.group = g;
43         this.daemon = parent.isDaemon();
44         this.priority = parent.getPriority();
45         if (security == null || isCCLOverridden(parent.getClass()))
46             this.contextClassLoader = parent.getContextClassLoader();
47         else
48             this.contextClassLoader = parent.contextClassLoader;
49         this.inheritedAccessControlContext =
50                 acc != null ? acc : AccessController.getContext();
51         this.target = target;
52         setPriority(priority);
53         if (parent.inheritableThreadLocals != null)
54             this.inheritableThreadLocals =
55                 ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
56         /* Stash the specified stack size in case the VM cares */
57         this.stackSize = stackSize;
58 
59         /* Set thread ID */
60         tid = nextThreadID();
61     }

被new出來的thread如果沒有特別設置它的daemon屬性,那它的daemon將和創建它的線程的daemon相同,Junit線程是daemon=true(后台線程),所以new出來的線程也是后台線程,當虛擬機中不存在daemon==false的線程后,虛擬機將會自動退出。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM