修改
正如@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)
sysctl kern.num_threads
:
kern.num_threads: 10240
答案 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