啟動一個最簡單的Java main程式時,有多少個執行緒被建立
事情的全部起因來自於這樣一個程式
public class VolatileTest {
public static volatile int race = 0;
public static void increase(){
race++;
}
private static final int THREADS_COUNT = 10;
public static void main(String[] args) {
Thread[] threads = new Thread[THREADS_COUNT];
for (int i = 0;i < THREADS_COUNT;i++){
threads[i] = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0;i < 10;i++){
increase();
}
}
});
threads[i].start();
}
while (Thread.activeCount() > 1){
System.out.println(Thread.activeCount());
Thread.yield();
}
System.out.println(race);
}
}
這是一個簡單的多執行緒下的計數器,用於說明volatile修飾的變數並不能完全解決多執行緒併發問題,體現在這段程式碼中就是最後列印的結果有可能<100。
這篇博文的主題不是討論volatile關鍵字的用法,而是你如果在linux下跑這段程式,會卡在死迴圈了出不來,各種百度,google,總算找到了問題,我們先來看一看,簡單啟動一個main程式時,有多少個執行緒被建立呢?
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false,false);
for (ThreadInfo info : threadInfos
) {
System.out.println("[" + info.getThreadId() + "]" + info.getThreadName());
}
System.out.println(Thread.activeCount());
最後列印結果如下
好,我們分別來看看這幾個執行緒都是幹嘛用的,這部分內容主要來自
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執行緒的幾點:
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,它主要用於處理引用物件本身(軟引用、弱引用、虛引用)的垃圾回收問題。
Monitor Ctrl-Break
這個執行緒我也不是很明白是幹什麼用的,oracle官網有詳細資訊,大家可以去看看
詳細連結
那問題來了,在linux下雖然建立了5個執行緒,但是當前活動執行緒只有兩個,main和Monitor Ctrl-Break,這就導致了,我們在等待所有子執行緒結束後的那句判斷程式碼應該是>2而不是>1!!!
while (Thread.activeCount() > 2){
System.out.println(Thread.activeCount());
Thread.yield();
}
結論
windows下這個Monitor Ctrl-Break是不算在活動執行緒的,所以這樣大於1是可以執行的,但是linux下應該是 大於2
相關文章
- 被問懵了:一個程式最多可以建立多少個執行緒?執行緒
- JVM原始碼分析之一個Java程式究竟能建立多少執行緒JVM原始碼Java執行緒
- java啟動執行緒時 extends與implements的一個差異Java執行緒
- 用BCB寫一個最簡單的多執行緒 (轉)執行緒
- 程式與執行緒的一個簡單解釋執行緒
- JVM程式用一個主執行緒來執行main()方法JVM執行緒AI
- windows 下一個程式能開多少個執行緒Windows執行緒
- JAVA執行緒池原理原始碼解析—為什麼啟動一個執行緒池,提交一個任務後,Main方法不會退出?Java執行緒原始碼AI
- 遊戲伺服器啟動多少個執行緒合適遊戲伺服器執行緒
- 一個簡單java程式的執行全過程Java
- Java多執行緒的建立和啟動Java執行緒
- 關於程式與執行緒的一個簡單解釋執行緒
- Linux中最多有多少程式?一個程式最多有多少執行緒?Linux執行緒
- 【Java基礎】:執行緒的建立和啟動Java執行緒
- 手動造一個執行緒池(Java)執行緒Java
- linux 實時檢視一個 python 程式有幾個執行緒LinuxPython執行緒
- 24. 一個普通main方法的執行,是單執行緒模式還是多執行緒模式?為什麼?AI執行緒模式
- 用Java編寫一個最簡單的桌面程式Java
- 建立一個簡單的小程式
- Swoole 啟動一個服務,開啟了哪些程式和執行緒?執行緒
- java 使用執行緒做一個簡單的ATM存取款例項.Java執行緒
- 多執行緒,到底該設定多少個執行緒?執行緒
- java 執行緒淺解01[建立以及啟動]Java執行緒
- VC啟動一個新執行緒的三種方法執行緒
- XNA“效率”探索——一個簡單的繁花曲執行緒序執行緒
- Java Main 如何是如何被執行的?JavaAI
- 什麼?一個核同時執行兩個執行緒?執行緒
- 最簡單的編寫基於執行緒的程式碼的方法之一:派生執行緒類(轉)執行緒
- 使用Dockerfile建立一個tomcat映象,並執行一個簡單war包DockerTomcat
- 死磕 java執行緒系列之自己動手寫一個執行緒池Java執行緒
- Java NIO 執行緒 的一個問題Java執行緒
- Java多執行緒——獲取多個執行緒任務執行完的時間Java執行緒
- 單執行緒的JS如何實現多個互動同時進行執行緒JS
- 畫江湖之 PHP 多執行緒開發 【建立一個新的執行緒】PHP執行緒
- 畫江湖之 PHP 多執行緒開發 [建立一個新的執行緒]PHP執行緒
- 執行緒和執行緒池的理解與java簡單例子執行緒Java單例
- java 最簡單的定時器,只需一行Java定時器
- 100行Java程式碼構建一個執行緒池Java執行緒