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