什么是JVM可以创建的阈值限制线程数

时间:2016-05-24 03:58:35

标签: java multithreading jvm

修改

正如@Petesh所说,我达到了kern.num_taskthreads限制,而不是整体线程限制,这限制了单个进程的线程数。

sysctl kern.num_taskthreads是:

kern.num_taskthreads: 2048

当我使用VM args -XX:ThreadStackSize=1g时,我只能创建 122 个线程; -XX:ThreadStackSize=2g创建了 58 个主题。这很合理。

但是,无论我如何更改-Xss args,结果总是 2031 ,这仍然很奇怪。 -Xss args似乎只适用于我现在不确定的主线程。

原始问题:

我运行了一个测试,以找出一个JVM可以创建多少个线程。当我调整JVM args -Xmx-Xss时,结果没有改变。

以下是代码:

public class ThreadTest {
    public static void main(String[] args) {
        int count = 0;
        try {
            while (true) {
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            TimeUnit.SECONDS.sleep(360);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                });
                thread.start();
                System.out.println(count);
            }

        } catch (Error e) {
            e.printStackTrace();
        }
    }
}

操作系统信息:

  
      
  • 型号名称:MacBook Pro
  •   
  • 型号标识符:MacBookPro11,4
  •   
  • 处理器名称:Intel Core i7
  •   
  • 处理器速度:2.2 GHz
  •   
  • 处理器数量:1
  •   
  • 核心总数:4
  •   
  • L2缓存(每个核心):256 KB
  •   
  • L3缓存:6 MB
  •   
  • 内存:16 GB
  •   

java版:

➤ java -version                                                                                                                                                          
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Dynamic Code Evolution 64-Bit Server VM (build 25.71-b01-dcevmlight-1, mixed mode)

结果: enter image description here

ulimit -aenter image description here

sysctl kern.num_threads

kern.num_threads: 10240

2 个答案:

答案 0 :(得分:3)

所有这些都是特定于操作系统的 - 在OSX的情况下,您已经获得了<script> {literal} $('#layout_feedback .feedback_button').on('click', function(){ if($('#layout_feedback .firststep .content').css('display', 'none') == true){ $('#layout_feedback .firststep .content').slideDown(); }else{ $('#layout_feedback .firststep .content').slideUp(); } }); $('#layout_feedback .firststep button').on('click', function(){ $('#layout_feedback .firststep').slideUp(); $('#layout_feedback .secondstep').slideDown(); setTimeout(function(){ $('#layout_feedback .firststep .content').slideUp(); $('#layout_feedback .secondstep .content').slideUp(); $('#layout_feedback .firststep').css('display','block'); $('#layout_feedback .secondstep').css('display','none'); $('#layout_feedback textarea').val(''); }, 5000); }); {/literal} 无法超出的每个进程的线程限制。您创建的线程数限制以及VM创建的线程的开销似乎表明您已达到该限制。

sysctl kern.num_taskthreads-XX:ThreadStackSize之间的差异有点奇怪。在这种情况下,我将我的分析基于OSX oracle java vm(您表示您正在使用不同的VM运行)。

-Xss<size>将堆栈大小设置为该字节数。存储它的变量将它除以1024.但是由于计算它的方式,该值最终为无意义的值(64位jvm,在linux和osx上检查) - 这是一些非常糟糕的溢出数学:

-Xss

当我们将其与for i in {1..8}; do echo "${i}G:"; java -Xss${i}g -XX:+PrintFlagsFinal -version 2>&1 | grep ' ThreadStack'; done 1G: intx ThreadStackSize := 1048576 {pd product} 2G: intx ThreadStackSize := 18014398507384832 {pd product} 3G: intx ThreadStackSize := 18014398508433408 {pd product} 4G: intx ThreadStackSize := 0 {pd product} 5G: intx ThreadStackSize := 1048576 {pd product} 6G: intx ThreadStackSize := 18014398507384832 {pd product} 7G: intx ThreadStackSize := 18014398508433408 {pd product} 8G: intx ThreadStackSize := 0 {pd product} 进行比较时,我们会有不同的图片:

首先,这些值按1024倍缩放 - 即所请求的所有值实际上是堆栈大小的KB数。

这意味着-XX:ThreadStackSize需要从-XX:ThreadstackSize的值开始指定1024倍。事实上,您只能创建一小部分线程,并且进程的虚拟内存大小使这一点显而易见(取自进程的vmmap输出):

-Xss
每堆4TB?这会受到伤害(这是你之前要求的):

一旦我们将其调低了1024倍,我们在第二次运行中获得相同数量的线程 - 您可以在输出中更清楚地看到这些数字,并且它们按照请求的大小线性缩放:

Stack                  0000000800004000-0000040800000000 [  4.0T] rw-/rwx SM=NUL  thread 23
Stack                  0000040800000000-0000040800003000 [   12K] rw-/rwx SM=PRV  thread 23

因此,看起来使用for i in {1..8}; do echo "${i}G:"; java -XX:ThreadStackSize=${i}m -XX:+PrintFlagsFinal -version 2>&1 | grep ' ThreadStack'; done 1G: intx ThreadStackSize := 1048576 {pd product} 2G: intx ThreadStackSize := 2097152 {pd product} 3G: intx ThreadStackSize := 3145728 {pd product} 4G: intx ThreadStackSize := 4194304 {pd product} 5G: intx ThreadStackSize := 5242880 {pd product} 6G: intx ThreadStackSize := 6291456 {pd product} 7G: intx ThreadStackSize := 7340032 {pd product} 8G: intx ThreadStackSize := 8388608 {pd product} 实际上只有在您查找&lt;堆栈大小时才有用。 1GB;如果您正在寻找&gt;的堆积大小1GB然后您可以使用-Xss<size>明确指定它。

找出溢出。代码parses the Xss option

-XX:ThreadStackSize

然后在恒星muppetry it does的行为中:

julong long_ThreadStackSize = 0;
ArgsRange errcode = parse_memory_size(tail, &long_ThreadStackSize, 1000);

即。将FLAG_SET_CMDLINE(intx, ThreadStackSize, round_to((int)long_ThreadStackSize, K) / K); 向下转换为long,然后传递给int。这需要round_to值,这是64位VM上的64位值。所以从我所知道的是,你开始的价值是:

Register

获取sign extended到:

0x80000000

除以1024(0x400): -

0xFFFFFFFF80000000

所以你可以看到前一个脚本中2GB值的来源。

我已经记录了一个错误。源中所需的更改而不是0x3FFFFFFFE00000 == 18,014,398,507,384,832 (int)long_ThreadStackSize应保持计算正确。

答案 1 :(得分:1)

我在linux jvm 1.8.0_92上测试它,它和你说的一样,我发现了这个:

What is the difference between -Xss and -XX:ThreadStackSize?

和oracle页面:

http://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

它说:

以下示例以不同为单位将线程堆栈大小设置为1024 KB:

   -Xss1m
   -Xss1024k
   -Xss1048576

This option is equivalent to -XX:ThreadStackSize