關於JVM系列面試知識點總結了一個思惟導圖,分享給你們java
McGovernTheory在StackOverflow提了這樣一個問題:程序員
這取決於你使用的CPU,操做系統,其餘進程正在作的事情,你使用的Java的版本,還有其餘的因素。我曾經見過一臺Windows服務器在宕機以前有超過6500個線程。固然,大多數線程什麼事情也沒有作。一旦一臺機器上有差很少6500個線程(Java裏面),機器就會開始出問題,並變得不穩定。面試
以個人經驗來看,JVM容納的線程與計算機自己性能是正相關的。服務器
固然了,你要有足夠的本機內存,而且給Java分配了足夠的內存,讓每一個線程均可以擁有棧(虛擬機棧),能夠作任何想作的事情。任何一臺擁有現代CPU(AMD或者是Intel最近的幾代)和1-2G內存(取決於操做系統)的機器很容易就能夠支持有上千個線程的Java虛擬機。多線程
若是你須要一個更精確的答案,最好是本身作壓測。函數
這裏有不少的參數(能夠設置)。對於特定的虛擬機,都會有本身的運行時參數。(最大線程數)必定程度上由操做系統決定的:底層的操做系統要給線程提供哪些支持?施加哪些限制?虛擬機使用的是原生的操做系統的線程仍是red thread或者green thread?性能
操做系統提供的支持是另外一個問題。若是你向下面這樣寫Java程序:測試
class DieLikeADog {
public static void main(String[] argv){
for(;;){
new Thread(new SomeRunaable).start();
}
}
}
(不要抱怨語法細節,這纔剛剛開始)那你固然但願能獲得成百上千個運行的線程。可是,建立一個線程的成本是相對較大的,(過多線程)調度的開銷會變得突出。可否讓這些線程作有用的事情還不肯定。spa
好了,火燒眉毛了!下面是個人一個加了點潤色的小的測試程序:操作系統
public class DieLikeADog {
private static Object s = new Object();
private static int count = 0;
public static void main(String[] argv){
for(;;){
new Thread(new Runnable(){
public void run(){
synchronized(s){
count += 1;
System.err.println("New thread #"+count);
}
for(;;){
try {
Thread.sleep(1000);
} catch (Exception e){
System.err.println(e);
}
}
}
}).start();
}
}
}
在Intel的OS/X 10.5.6系統上,Java 5的輸出以下:
New thread #2547
New thread #2548
New thread #2549
Can't create thread: 5
New thread #2550
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:592)
at DieLikeADog.main(DieLikeADog.java:6)
讀了Charlie Martin的回覆之後,我很想知道堆內存的大小是否可以給建立的線程數帶來不一樣,而後我就被結果驚呆了:在Vista Home Premium SP1系統上,使用JDK 1.6.0_11,設置堆內存的大小從2M到1024M來執行Charlie的測試程序。好比:建立2M的堆內存,我使用的虛擬機參數是:-Xms2m -Xmx2m.
下面是個人測試結果:
2 mb --> 5744 threads
4 mb --> 5743 threads
8 mb --> 5735 threads
12 mb --> 5724 threads
16 mb --> 5712 threads
24 mb --> 5687 threads
32 mb --> 5662 threads
48 mb --> 5610 threads
64 mb --> 5561 threads
96 mb --> 5457 threads
128 mb --> 5357 threads
192 mb --> 5190 threads
256 mb --> 5014 threads
384 mb --> 4606 threads
512 mb --> 4202 threads
768 mb --> 3388 threads
1024 mb --> 2583 threads
因此,堆的大小確實很重要。可是,堆大小和最大線程數倒是呈反比例關係。
這太詭異了!
絕對理論上的最大線程數是進程的用戶地址空間除以線程棧的大小(現實中,若是內存所有給線程棧使用,就不會有能運行的程序了)。所以,以32位Windows系統爲例,每個進程的用戶地址空間是2G,假如每一個線程棧的大小是128K,最多會有16384(=2*1024*1024 / 128)個線程。實際在XP系統上,我發現大約能啓動13000個線程。
而後,我認爲,你的問題本質上是:(a)你是否能夠在你的代碼中有效的管理許多的線程,不讓他們作很顯然是愚蠢的事情(好比:讓他們在同一個object對象上等待隨後被調用notifyAll()…),(b)操做系統是否能夠有效地管理這許多線程。基本上來講,若是(a)的答案是」yes」的話,(b)的答案也是」yes」。
很巧的是,你能夠在Thread的構造函數中設置線程棧的大小,可是,你不須要也不該該把這個和虛擬機參數弄混淆。
關注公衆號:程序員白楠楠, 領取2020最新Java面試題手冊(200多頁PDF文檔)。