java线程运行无限次_java程序运行时到底有多少个活跃线程
先貼上最原始的代碼,疑惑的開始。
public class Solution {
public static void main(String[] args) {
T t1 = new T();
T t2 = new T();
t1.start();
System.out.println(Thread.activeCount());
t2.start();
}
static class T extends Thread{
@Override
public void run() {
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
上面的程序應該輸出數字2?還是3?本著嚴謹的態度在ide上面跑了一下,本來以為是2,結果是3. t2的運行不是在打印之前嘛?為什么會是3呢?難道說t2也算進去了?繼續去測試一下。
public static void main(String[] args) {
T t1 = new T();
T t2 = new T();
t1.start();
System.out.println(Thread.activeCount());
t2.start();
System.out.println(Thread.activeCount());
}
結果是3 4.這就說明另外一個活躍的線程不是它t2,另外有一個線程。順著這個思路,去看看到底哪些線程在運行。
public static void main(String[] args) {
T t1 = new T();
T t2 = new T();
t1.start();
System.out.println(Thread.activeCount());
Map maps = Thread.getAllStackTraces();
for ( Thread thread:maps.keySet()){
System.out.println(thread.getName());
}
t2.start();
System.out.println(Thread.activeCount());
}
把所有的線程都打印出來看看。下面是運行結果。
1.png
運行結果讓人大吃一驚,這是什么啊,不算t2都有7個活躍的進程,為什么Thread.activeCount()只有3或者4個呢?這是什么鬼哦。為了搞清楚到底是怎么回事,就去看看Thread.activeCount()的源碼吧。下面展示的就是源碼部分。
/**
* Returns an estimate of the number of active threads in the current
* thread's {@linkplain java.lang.ThreadGroup thread group} and its
* subgroups. Recursively iterates over all subgroups in the current
* thread's thread group.
*
*
The value returned is only an estimate because the number of
* threads may change dynamically while this method traverses internal
* data structures, and might be affected by the presence of certain
* system threads. This method is intended primarily for debugging
* and monitoring purposes.
*
* @return an estimate of the number of active threads in the current
* thread's thread group and in any other thread group that
* has the current thread's thread group as an ancestor
*/
public static int activeCount() {
return currentThread().getThreadGroup().activeCount();
}
看了源碼,我們了解到原來Thread.activeCount()只是計算當前線程的線程組里面有多少活躍線程,而不是所有的活躍線程,這也就解釋了,為什么會出現數目對不上的情況。接下來,我們看看每個線程組都是哪些線程。
public static void main(String[] args) {
T t1 = new T();
T t2 = new T();
t1.start();
System.out.println("當前活躍線程數量:"+Thread.activeCount());
ThreadGroup group = Thread.currentThread().getThreadGroup();
System.out.println("當前線程組的名稱:"+group.getName());
Thread[] list1 = new Thread[group.activeCount()];
group.enumerate(list1);
for (Thread thread:list1){
System.out.println(thread.getName());
}
ThreadGroup groupParent = group.getParent();
System.out.println("當前線程組的名稱:"+groupParent.getName());
Thread[] list2 = new Thread[groupParent.activeCount()];
groupParent.enumerate(list2);
for (Thread thread:list2){
System.out.println(thread.getName());
}
}
上面程序的運行結果如下圖所示。
2.png
這次基本就清清楚楚,明明白白了。其中Thread-0就是我們的t1線程。接下來簡單的描述一下其他的線程都是干什么的。參考http://ifeve.com/jvm-thread/
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線程的幾點:
只有當開始一輪垃圾收集時,才會開始調用finalize()方法;因此并不是所有對象的finalize()方法都會被執行;
該線程也是daemon線程,因此如果虛擬機中沒有其他非daemon線程,不管該線程有沒有執行完finalize()方法,JVM也會退出;
JVM在垃圾收集時會將失去引用的對象包裝成Finalizer對象(Reference的實現),并放入ReferenceQueue,由Finalizer線程來處理;最后將該Finalizer對象的引用置為null,由垃圾收集器來回收;
JVM為什么要單獨用一個線程來執行finalize()方法呢?如果JVM的垃圾收集線程自己來做,很有可能由于在finalize()方法中誤操作導致GC線程停止或不可控,這對GC線程來說是一種災難;
Reference Handler
VM在創建main線程后就創建Reference Handler線程,其優先級最高,為10,它主要用于處理引用對象本身(軟引用、弱引用、虛引用)的垃圾回收問題。
Monitor Ctrl-Break
用于監控目的,監控Ctrl-Break中斷信號的。
總結
以上是生活随笔為你收集整理的java线程运行无限次_java程序运行时到底有多少个活跃线程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 重庆找Java开发工作_重庆【Java开
- 下一篇: java 线上运维_一次java应用线上