Java的線程對象是存儲在堆上的,因此,可以建立多少個線程,受到堆空間的大小限制,同時也受到每一個線程的大小的限制,假如線程對象內部有一個很是大的數組字段,那就很是影響可以建立的線程的大小java
咱們的例子:數組
class Task implements Runnable { //5M堆內存 128k的狀況下,最多建立31個線程就掛了 byte[] bytes = new byte[1024 * 128]; @Override public void run() { while (true) { try { bytes[0] = 1; Thread.sleep(10_100); } catch (InterruptedException e) { e.printStackTrace(); } } } }
線程對象內部持有一個數組字段,這個數組的大小是128k,咱們的測試代碼:jvm
public static void threadTest3() { int count = 1; try { while (true) { Thread thread = new Thread(new Task()); thread.start(); System.out.println("==============================================" + count++); } } catch (Throwable e) { System.out.println(count); e.printStackTrace(); } }
運行測試的時候,咱們將堆的內存設置的小一些:ide
-Xmx5m -Xms5m XX:+PrintGC -XX:-PrintGCDetails測試
輸出的日誌以下:spa
"C:\Program Files\Java\jdk1.8.0_152\bin\java.exe" -Xmx5m -Xms5m -XX:+PrintGC -XX:-PrintGCDetails com.jiaoyiping.baseproject.concurrent.ThreadTest [GC (Allocation Failure) 1024K->732K(5632K), 0.0006644 secs] [GC (Allocation Failure) 1746K->1023K(5632K), 0.0012964 secs] [GC (Allocation Failure) 1818K->1417K(5632K), 0.0005073 secs] [GC (Allocation Failure) 2441K->1546K(5632K), 0.0008099 secs] [GC (Allocation Failure) 2570K->1773K(5632K), 0.0009678 secs] ==============================================1 [GC (Allocation Failure) 2752K->2046K(5632K), 0.0012278 secs] ==============================================2 ==============================================3 ==============================================4 ==============================================5 ==============================================6 ==============================================7 ==============================================8 [GC (Allocation Failure) 2962K->3022K(5632K), 0.0007815 secs] ==============================================9 ==============================================10 ==============================================11 ==============================================12 ==============================================13 ==============================================14 ==============================================15 [GC (Allocation Failure) 3938K->3950K(5632K), 0.0005197 secs] [Full GC (Ergonomics) 3950K->3132K(5632K), 0.0098480 secs] ==============================================16 ==============================================17 ==============================================18 ==============================================19 ==============================================20 ==============================================21 ==============================================22 [GC (Allocation Failure) 4090K->4220K(5632K), 0.0004522 secs] [Full GC (Ergonomics) 4220K->3975K(5632K), 0.0085720 secs] ==============================================23 ==============================================24 ==============================================25 ==============================================26 ==============================================27 ==============================================28 ==============================================29 [Full GC (Ergonomics) 4920K->4876K(5632K), 0.0110795 secs] [Full GC (Allocation Failure) 4876K->4856K(5632K), 0.0086577 secs] ==============================================30 [Full GC (Ergonomics) 5015K->4985K(5632K), 0.0025122 secs] [Full GC (Allocation Failure) 4985K->4985K(5632K), 0.0022044 secs] 31 java.lang.OutOfMemoryError: Java heap space at com.jiaoyiping.baseproject.concurrent.Task.<init>(ThreadTest.java:105) at com.jiaoyiping.baseproject.concurrent.ThreadTest.threadTest3(ThreadTest.java:74) at com.jiaoyiping.baseproject.concurrent.ThreadTest.main(ThreadTest.java:17) [Full GC (Ergonomics) 5118K->4995K(5632K), 0.0108311 secs] [Full GC (Ergonomics) 5107K->5029K(5632K), 0.0034520 secs] [Full GC (Ergonomics) 5107K->5058K(5632K), 0.0034841 secs] [Full GC (Ergonomics) 5107K->5064K(5632K), 0.0032645 secs] [Full GC (Ergonomics) 5107K->5097K(5632K), 0.0034425 secs] [Full GC (Ergonomics) 5107K->5107K(5632K), 0.0030512 secs] [Full GC (Ergonomics) 5107K->5107K(5632K), 0.0027000 secs] [Full GC (Ergonomics) 5109K->5109K(5632K), 0.0026329 secs] [Full GC (Ergonomics) 5111K->5111K(5632K), 0.0026942 secs] [Full GC (Ergonomics) 5113K->5113K(5632K), 0.0024612 secs] [Full GC (Ergonomics) 5116K->5116K(5632K), 0.0028061 secs] [Full GC (Ergonomics) 5118K->5118K(5632K), 0.0027730 secs] [Full GC (Ergonomics) 5119K->5119K(5632K), 0.0039374 secs] [Full GC (Allocation Failure) 5119K->5118K(5632K), 0.0037878 secs] [Full GC (Ergonomics) 5119K->5119K(5632K), 0.0031486 secs] [Full GC (Allocation Failure) 5119K->5119K(5632K), 0.0028138 secs]
當建立了30個線程的時候,就出現了堆內存的溢出操作系統
若是將bytes的值改變爲56K呢,能夠建立70個線程線程
-Xss影響的是棧的深度(好比棧的深度大的話,可以遞歸調用的次數就越多)
咱們構造出來遞歸調用的例子,用來測試-Xss參數對遞歸調用的次數的影響日誌
public static void threadTest4() { try { add(0); } catch (Throwable throwable) { throwable.printStackTrace(); } } static int add(int count) { System.out.println("invoke count" + (count + 1)); return add(count + 1); }
當-Xss設置爲128k的時候:
code
當-Xss設置爲256K的時候:
jvm推薦的-Xss設置最少是108k,小於108K的時候,結果是不可預料的
5k-64k 沒法建立虛擬機:
4k和如下很大的數值:
64K- 108K
這個值默認是1M咱們通常不須要修改,值須要知道-Xss和棧的深度有關便可,經過以上的例子咱們獲得如下結論:堆內存的大小,和線程對象自己的大小,影響可以建立的線程的個數,-Xss影響棧的深度
除了Java虛擬機以外,操做系統也會對能建立多少個進程和線程進行限制
經過兩個文件咱們能夠查看和修改這些限制數:
最大的PID
/proc/sys/kernel/threads-max
最多的線程數:
/proc/sys/kernel/pid_max