JVM可支援的最大執行緒數(轉)
摘自:http://sesame.iteye.com/blog/622670
工作中碰到過這個問題好幾次了,覺得有必要總結一下,所以有了這篇文章,這篇文章分為三個部分:認識問題、分析問題、解決問題。
一、認識問題:
首先我們通過下面這個 測試程式 來認識這個問題:
執行的環境 (有必要說明一下,不同環境會有不同的結果):32位 Windows XP,Sun JDK 1.6.0_18, eclipse 3.4,
測試程式:
import java.util.concurrent.CountDownLatch; public class TestNativeOutOfMemoryError { public static void main(String[] args) { for (int i = 0;; i++) { System.out.println("i = " + i); new Thread(new HoldThread()).start(); } } } class HoldThread extends Thread { CountDownLatch cdl = new CountDownLatch(1); public HoldThread() { this.setDaemon(true); } public void run() { try { cdl.await(); } catch (InterruptedException e) { } } }
不指定任何JVM引數,eclipse中直接執行輸出,看到了這位朋友了吧:
i = 5602
Exception in thread “main” java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:597)
at TestNativeOutOfMemoryError.main(TestNativeOutOfMemoryError.java:20)
二、分析問題:
這個異常問題本質原因是我們建立了太多的執行緒,而能建立的執行緒數是有限制的,導致了異常的發生。能建立的執行緒數的具體計算公式如下:
(MaxProcessMemory – JVMMemory – ReservedOsMemory) / (ThreadStackSize) = Number of threads
MaxProcessMemory 指的是一個程式的最大記憶體
JVMMemory JVM記憶體
ReservedOsMemory 保留的作業系統記憶體
ThreadStackSize 執行緒棧的大小
在java語言裡, 當你建立一個執行緒的時候,虛擬機器會在JVM記憶體建立一個Thread物件同時建立一個作業系統執行緒,
而這個系統執行緒的記憶體用的不是JVMMemory,而是系統中剩下的記憶體(MaxProcessMemory – JVMMemory – ReservedOsMemory)。
結合上面例子我們來對公式說明一下:
MaxProcessMemory 在32位的 windows下是 2G
JVMMemory eclipse預設啟動的程式記憶體是64M
ReservedOsMemory 一般是130M左右
ThreadStackSize 32位 JDK 1.6預設的stacksize 325K左右
公式如下:
(2*1024*1024-64*1024-130*1024)/325 = 5841
公式計算所得5841,和實踐5602基本一致(有偏差是因為ReservedOsMemory不能很精確)
由公式得出結論:你給JVM記憶體越多,那麼你能建立的執行緒越少,越容易發生java.lang.OutOfMemoryError: unable to create new native thread。
咦,有點揹我們的常理,恩,讓我們來驗證一下,依舊使用上面的測試程式,加上下面的JVM引數,測試結果如下:
ThreadStackSize JVMMemory 能建立的執行緒數
預設的325K -Xms1024m -Xmx1024m i = 2655
預設的325K -Xms1224m -Xmx1224m i = 2072
預設的325K -Xms1324m -Xmx1324m i = 1753
預設的325K -Xms1424m -Xmx1424m i = 1435
-Xss1024k -Xms1424m -Xmx1424m i = 452
完全和公式一致。
三、解決問題:
1, 如果程式中有bug,導致建立大量不需要的執行緒或者執行緒沒有及時回收,那麼必須解決這個bug,修改引數是不能解決問題的。
2, 如果程式確實需要大量的執行緒,現有的設定不能達到要求,那麼可以通過修改MaxProcessMemory,JVMMemory,ThreadStackSize這三個因素,來增加能建立的執行緒數:
a, MaxProcessMemory 使用64位作業系統
b, JVMMemory 減少JVMMemory的分配
c, ThreadStackSize 減小單個執行緒的棧大小
四、其他:
在java應用中,有時候會出現這樣的錯誤:OutOfMemoryError: unable to create new native thread.這種怪事是因為JVM已經被系統分配了大量的記憶體(比如1.5G),並且它至少要佔用可用記憶體的一半。有人發現,線上程個數很多的情況下,你分配給JVM的記憶體越多,那麼,上述錯誤發生的可能性就越大。
每一個32位的程式最多可以使用2G的可用記憶體,因為另外2G被作業系統保留。這裡假設使用1.5G給JVM,那麼還餘下500M可用記憶體。這500M記憶體中的一部分必須用於系統dll的載入,那麼真正剩下的也許只有400M,現在關鍵的地方出現了:當你使用Java建立一個執行緒,在JVM的記憶體裡也會建立一個Thread物件,但是同時也會在作業系統裡建立一個真正的物理執行緒(參考JVM規範),作業系統會在餘下的400兆記憶體裡建立這個物理執行緒,而不是在JVM的1500M的記憶體堆裡建立。在jdk1.4裡頭,預設的棧大小是256KB,但是在jdk1.5裡頭,預設的棧大小為1M每執行緒,因此,在餘下400M的可用記憶體裡邊我們最多也只能建立400個可用執行緒。
這樣結論就出來了,要想建立更多的執行緒,你必須減少分配給JVM的最大記憶體。還有一種做法是讓JVM宿主在你的JNI程式碼裡邊。
給出一個有關能夠建立執行緒的最大個數的估算公式:
(MaxProcessMemory – JVMMemory – ReservedOsMemory) / (ThreadStackSize) = Number of threads
對於jdk1.5而言,假設作業系統保留120M記憶體:
1.5GB JVM: (2GB-1.5Gb-120MB)/(1MB) = ~380 threads
1.0GB JVM: (2GB-1.0Gb-120MB)/(1MB) = ~880 threads
對於棧大小為256KB的jdk1.4而言,
1.5GB allocated to JVM: ~1520 threads
1.0GB allocated to JVM: ~3520 threads
http://blog.csdn.net/xyls12345/article/details/26482387
相關文章
- java 最大執行緒數Java執行緒
- java 最大執行緒數理解Java執行緒
- 執行緒池中的最大執行緒數、核心執行緒數和佇列大小的合理設定執行緒佇列
- 證明執行緒池ThreadPoolExecutor的核心執行緒數,最大執行緒數,佇列長度的關係執行緒thread佇列
- JVM中的執行緒行為JVM執行緒
- 深入理解JVM(③)執行緒與Java的執行緒JVM執行緒Java
- mysql關於最大連線數、最大併發執行緒數的區別MySql執行緒
- Java執行緒池核心執行緒用盡後為何優先排隊而不是繼續建立執行緒直至最大執行緒數?Java執行緒
- JVM 進行執行緒同步背後的原理JVM執行緒
- JVM找出佔用CPU最高的執行緒JVM執行緒
- 執行緒 (轉)執行緒
- 關於jboss最大執行緒數滿導致服務停止執行緒
- JVM 執行緒池發展趨勢JVM執行緒
- Java 可中斷執行緒Java執行緒
- 執行緒轉儲:命名你的執行緒和檢視系統(轉)執行緒
- 一步步瞭解執行緒池之可重用固定執行緒數-FixedThreadPool執行緒thread
- JVM程式用一個主執行緒來執行main()方法JVM執行緒AI
- SpringBoot 對多執行緒的支援Spring Boot執行緒
- 深入理解JVM(③)再談執行緒安全JVM執行緒
- 從Java到JVM到OS執行緒睡眠JavaJVM執行緒
- 跟著sleep看jvm執行緒變化JVM執行緒
- 檢視和診斷JVM執行緒資訊JVM執行緒
- 多執行緒(2)-執行緒同步條件變數執行緒變數
- python多執行緒程式設計1— python對多執行緒的支援Python執行緒程式設計
- 玩轉java多執行緒 之多執行緒基礎 執行緒狀態 及執行緒停止實戰Java執行緒
- 可重入性和執行緒安全執行緒
- 檢視JVM執行時引數JVM
- Java執行緒(篇外篇):執行緒本地變數ThreadLocalJava執行緒變數thread
- Qt入門(9)——Qt中的執行緒支援QT執行緒
- 求教:jboss對多執行緒併發的支援執行緒
- 如何檢視CPU核數和執行緒數?CPU的核心數、執行緒數的關係和區別執行緒
- java 對執行緒安全支援有哪些?Java執行緒
- c#基礎,單執行緒,跨執行緒訪問和執行緒帶引數C#執行緒
- 摩爾執行緒釋出多款國產顯示卡,支援 Windows+DirectX 可玩主流遊戲執行緒Windows遊戲
- .net使用Task多執行緒執行任務 .net限制執行緒數量執行緒
- 從 JVM 記憶體模型談執行緒安全JVM記憶體模型執行緒
- 理解JVM(六):執行緒安全和鎖優化JVM執行緒優化
- JVM 執行緒堆疊分析過程詳解JVM執行緒