什么是 JVM 可以创建的线程的阈值限制数
What is threshold limit number of threads that a JVM can create
编辑:
正如@Petesh 所说,我达到了 kern.num_taskthreads
限制而不是总线程限制,这限制了单个进程的线程数。
sysctl kern.num_taskthreads
是:
kern.num_taskthreads: 2048
当我使用 VM args -XX:ThreadStackSize=1g
时,我只能创建 122 个线程;创建了 -XX:ThreadStackSize=2g
、58 个线程。有道理。
但仍然是 st运行ge,无论我如何更改 -Xss
参数,结果始终是 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();
}
}
}
以及 OS 信息:
- Model Name: MacBook Pro
- Model Identifier: MacBookPro11,4
- Processor Name: Intel Core i7
- Processor Speed: 2.2 GHz
- Number of Processors: 1
- Total Number of Cores: 4
- L2 Cache (per Core): 256 KB
- L3 Cache: 6 MB
- Memory: 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)
结果:
ulimit -a
:
sysctl kern.num_threads
:
kern.num_threads: 10240
我在我的linux jvm 1.8.0_92上测试了一下,和你说的一样,我发现:
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
所有这些东西都是 OS 特定的 - 在 OSX 的情况下,你有一个不能超过 sysctl kern.num_taskthreads
的每进程线程限制.您创建的线程数限制和 VM 创建线程的开销似乎表明您已达到该限制。
-XX:ThreadStackSize
和 -Xss<size>
之间的区别有点奇怪。在这种情况下,我的分析基于 OSX oracle java 虚拟机(您表示您是 运行 不同的虚拟机)。
-Xss
将堆栈大小设置为 该字节数 。存储它的变量将它除以 1024。但是由于它计算它的方式,该值最终成为一个无意义的值(64 位 jvm,检查 linux 和 osx)——这是一些非常糟糕的溢出数学:
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}
当我们将其与 -XX:ThreadStackSize
进行比较时,我们得到了不同的画面:
首先,这些值按 1024 倍缩放 - 即所有请求的值实际上都是堆栈大小的 KB 数。
这意味着 -XX:ThreadstackSize
需要比 -Xss
的值低 1024 倍。事实上,您只能创建线程数的一小部分,并且进程的虚拟内存大小使这一点显而易见(取自进程的 vmmap 输出):
Stack 0000000800004000-0000040800000000 [ 4.0T] rw-/rwx SM=NUL thread 23
Stack 0000040800000000-0000040800003000 [ 12K] rw-/rwx SM=PRV thread 23
每个堆栈 4TB?那会很痛(这是你之前要求的):
一旦我们将其向下调整 1024 倍,我们将在第二个中获得相同数量的线程 运行 - 您可以在输出中更清楚地看到这些数字,并且它们与请求的线性比例尺码:
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}
因此,看起来使用 -Xss<size>
确实只在您寻找小于 1GB 的堆栈大小时才有用;如果您正在寻找 > 1GB 的堆栈大小,那么您可以使用 -XX:ThreadStackSize
.
明确指定它
找出溢出。 parses the Xss option:
的代码
julong long_ThreadStackSize = 0;
ArgsRange errcode = parse_memory_size(tail, &long_ThreadStackSize, 1000);
然后在恒星布偶表演中 it does:
FLAG_SET_CMDLINE(intx, ThreadStackSize,
round_to((int)long_ThreadStackSize, K) / K);
即将 long
向下转换为 int
,然后传递给 round_to
。这需要一个 Register
值,这是 64 位 VM 上的 64 位值。所以据我所知,你开始的价值是:
0x80000000
获取 sign extended 到:
0xFFFFFFFF80000000
除以 1024 (0x400):-
0x3FFFFFFFE00000 == 18,014,398,507,384,832
这样您就可以看到前面脚本中的 2GB 值是从哪里来的。
我记录了一个错误。源代码中需要的更改不是 (int)long_ThreadStackSize
,应该是 (Register)long_ThreadStackSize
以保持计算正确。
编辑:
正如@Petesh 所说,我达到了 kern.num_taskthreads
限制而不是总线程限制,这限制了单个进程的线程数。
sysctl kern.num_taskthreads
是:
kern.num_taskthreads: 2048
当我使用 VM args -XX:ThreadStackSize=1g
时,我只能创建 122 个线程;创建了 -XX:ThreadStackSize=2g
、58 个线程。有道理。
但仍然是 st运行ge,无论我如何更改 -Xss
参数,结果始终是 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();
}
}
}
以及 OS 信息:
- Model Name: MacBook Pro
- Model Identifier: MacBookPro11,4
- Processor Name: Intel Core i7
- Processor Speed: 2.2 GHz
- Number of Processors: 1
- Total Number of Cores: 4
- L2 Cache (per Core): 256 KB
- L3 Cache: 6 MB
- Memory: 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)
结果:
ulimit -a
:
sysctl kern.num_threads
:
kern.num_threads: 10240
我在我的linux jvm 1.8.0_92上测试了一下,和你说的一样,我发现:
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
所有这些东西都是 OS 特定的 - 在 OSX 的情况下,你有一个不能超过 sysctl kern.num_taskthreads
的每进程线程限制.您创建的线程数限制和 VM 创建线程的开销似乎表明您已达到该限制。
-XX:ThreadStackSize
和 -Xss<size>
之间的区别有点奇怪。在这种情况下,我的分析基于 OSX oracle java 虚拟机(您表示您是 运行 不同的虚拟机)。
-Xss
将堆栈大小设置为 该字节数 。存储它的变量将它除以 1024。但是由于它计算它的方式,该值最终成为一个无意义的值(64 位 jvm,检查 linux 和 osx)——这是一些非常糟糕的溢出数学:
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}
当我们将其与 -XX:ThreadStackSize
进行比较时,我们得到了不同的画面:
首先,这些值按 1024 倍缩放 - 即所有请求的值实际上都是堆栈大小的 KB 数。
这意味着 -XX:ThreadstackSize
需要比 -Xss
的值低 1024 倍。事实上,您只能创建线程数的一小部分,并且进程的虚拟内存大小使这一点显而易见(取自进程的 vmmap 输出):
Stack 0000000800004000-0000040800000000 [ 4.0T] rw-/rwx SM=NUL thread 23
Stack 0000040800000000-0000040800003000 [ 12K] rw-/rwx SM=PRV thread 23
每个堆栈 4TB?那会很痛(这是你之前要求的):
一旦我们将其向下调整 1024 倍,我们将在第二个中获得相同数量的线程 运行 - 您可以在输出中更清楚地看到这些数字,并且它们与请求的线性比例尺码:
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}
因此,看起来使用 -Xss<size>
确实只在您寻找小于 1GB 的堆栈大小时才有用;如果您正在寻找 > 1GB 的堆栈大小,那么您可以使用 -XX:ThreadStackSize
.
找出溢出。 parses the Xss option:
的代码julong long_ThreadStackSize = 0;
ArgsRange errcode = parse_memory_size(tail, &long_ThreadStackSize, 1000);
然后在恒星布偶表演中 it does:
FLAG_SET_CMDLINE(intx, ThreadStackSize,
round_to((int)long_ThreadStackSize, K) / K);
即将 long
向下转换为 int
,然后传递给 round_to
。这需要一个 Register
值,这是 64 位 VM 上的 64 位值。所以据我所知,你开始的价值是:
0x80000000
获取 sign extended 到:
0xFFFFFFFF80000000
除以 1024 (0x400):-
0x3FFFFFFFE00000 == 18,014,398,507,384,832
这样您就可以看到前面脚本中的 2GB 值是从哪里来的。
我记录了一个错误。源代码中需要的更改不是 (int)long_ThreadStackSize
,应该是 (Register)long_ThreadStackSize
以保持计算正确。