啟動一個最簡單的Java main程序時,有多少個線程被創建


  在java中,啟動一個簡單的main程序,並不是只是單單創建了一個main線程而已,JVM會自動創建一些輔助用的線程,主要有以下幾個:

  Attach Listener:Attach Listener線程是負責接收到外部的命令,而對該命令進行執行的並且吧結果返回給發送者。通常我們會用一些命令去要求jvm給我們一些反 饋信 息,如:java -version、jmap、jstack等等。如果該線程在jvm啟動的時候沒有初始化,那么,則會在用戶第一次執行jvm命令時,得到啟動。

  Signal Dispatcher:前面我們提到第一個Attach Listener線程的職責是接收外部jvm命令,當命令接收成功后,會交給signal dispather線程去進行分發到各個不同的模塊處理命令,並且返回處理結果。signal dispather線程也是在第一次接收外部jvm命令時,進行初始化工作。

  Finalizer:這個線程也是在main線程之后創建的,其優先級為10,主要用於在垃圾收集前,調用對象的finalize()方法;關於Finalizer線程的幾點:

  1)只有當開始一輪垃圾收集時,才會開始調用finalize()方法;因此並不是所有對象的finalize()方法都會被執行;

  2)該線程也是daemon線程,因此如果虛擬機中沒有其他非daemon線程,不管該線程有沒有執行完finalize()方法,JVM也會退出;

  3) JVM在垃圾收集時會將失去引用的對象包裝成Finalizer對象(Reference的實現),並放入ReferenceQueue,由Finalizer線程來處理;最后將該Finalizer對象的引用置為null,由垃圾收集器來回收;

  4) JVM為什么要單獨用一個線程來執行finalize()方法呢?如果JVM的垃圾收集線程自己來做,很有可能由於在finalize()方法中誤操作導致GC線程停止或不可控,這對GC線程來說是一種災難;

  Reference Handler:VM在創建main線程后就創建Reference Handler線程,其優先級最高,為10,它主要用於處理引用對象本身(軟引用、弱引用、虛引用)的垃圾回收問題。

以上這部分內容引用自 http://ifeve.com/jvm-thread/,可以取這個地址查看更多線程的信息

這4個線程,加上,main,所以總共會有5個線程被創建,可以通過這幾行代碼來查看

ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();

ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false,false);

for (ThreadInfo info : threadInfos ) {

  System.out.println("[" + info.getThreadId() + "]" + info.getThreadName());

}

  但是,當前活動的線程只有1個,就是main,System.out.println(Thread.activeCount()); 用這條命令返回值是1。這也經常被用作以下場合的判斷

比如,在main線程中創建多個子線程后,如果子線程的耗時比main線程要長,main線程就會再子線程之前結束。假如main線程的結果需要用到子線程的返回值,那么我們通常就在main線程中加上這句代碼:

  System.out.println(Thread.activeCount() >1),

來判斷子線程是否全部運行結束,也就是當前活動線程只有main線程一個。這樣做在windows下是沒錯的,但是!!!

在linux下就不是這樣了,你會發現,即使所有的子線程全部結束,打印當前的活動線程是2!!!而不是1,除了main線程之外,linux下還會有一個Monitor Ctrl-Break 線程存在,這個線程是用來干嘛的呢?

Monitoring Thread Activity With Thread Dumps Thread dumps, or "thread stack traces," reveal information about an application's activity that can help you diagnose problems and better optimize application and JVM performance; for example, thread dumps can show the occurrence of "deadlock" conditions, which can seriously impact application performance. You can create a thread dump by invoking a control break (usually by pressing Ctrl-Break or Ctrl-\ or SIGQUIT on linux). This section provides information on working with thread dumps. It includes information on these subjects: 1.Lock Information in Thread Dumps 2.Detecting Deadlocks

這是oracle官網的原話。大家可以自行翻譯。 結論:在windows下可以用 Thread.activeCount() >1來判斷子線程是否全部結束,但是linux中應該是 Thread.activeCount() > 2


免責聲明!

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



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