当前位置:Java -> 探讨堆栈大小对JVM线程创建的影响:揭秘一个神话

探讨堆栈大小对JVM线程创建的影响:揭秘一个神话

在Java开发人员中,普遍存在这样一种观点,即可以在Java虚拟机(JVM)内创建的原生线程数量与堆栈大小有关。为了对这个普遍看法进行审查,进行了一项实验。结果表明,与先前想法相比,堆栈大小在原生线程创建中起到的作用较小。

实验

实验使用了以下Java程序,该程序不断创建线程并使用AtomicInteger对它们进行计数。

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;

public class ThreadCounter {
   public static void main(String[] args) {
       AtomicInteger counter = new AtomicInteger();

       while (true) {
           Thread thread = new Thread(() -> {
               counter.incrementAndGet();
               if (counter.get() % 100 == 0) {
                   System.out.printf("Number of threads created so far: %d%n", counter.get());
               }
               LockSupport.park();
           });
           thread.start();
       }
   }
}


测试环境

测试在具有以下配置的计算机上运行:

  • 处理器:Apple M1 Max
  • 内存:64 GB
  • 操作系统:macOS Vancura
  • Java版本:OpenJDK 21

实验结果

默认堆栈大小

初始测试使用了默认的堆栈大小2048 KB。在触发OutOfMemoryError之前,大约创建了16300个线程。

到目前为止创建的线程数量:16300。

Number of threads created so far: 16300
[3.566s][warning][os,thread] Failed to start thread "Unknown thread" - pthread_create failed (EAGAIN) for attributes: stacksize: 2048k, guardsize: 16k, detached.
[3.566s][warning][os,thread] Failed to start the native thread for java.lang.Thread "Thread-16354"
Exception in thread "main" java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached


计算表明,这16300个线程所需的内存约为31.875 GB,远低于64 GB的总内存。

10 MB堆栈大小

要将堆栈大小更改为10 MB,使用了以下JVM选项:

-XX:ThreadStackSize=10240 


OutOfMemoryError再次发生之前,程序产生了类似的结果- 16300个线程。

到目前为止创建的线程数量:16300。

Number of threads created so far: 16300
[3.995s][warning][os,thread] Failed to start thread "Unknown thread" - pthread_create failed (EAGAIN) for attributes: stacksize: 10240k, guardsize: 16k, detached.
[3.995s][warning][os,thread] Failed to start the native thread for java.lang.Thread "Thread-16354"
Exception in thread "main" java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached
	at java.base/java.lang.Thread.start0(Native Method)


如果您想使用IntelliJ IDEA,可以配置堆栈大小,并查看以下图片:

ThreadStackSize

1 GB堆栈大小

最后,对于最极端的情况,堆栈大小设置为1 GB:

-XX:ThreadStackSize=1048576 


值得注意的是,程序再次在大约16300个线程处达到上限,这强化了在先前的测试中观察到的模式。

到目前为止创建的线程数量:16300。

Number of threads created so far: 16200
Number of threads created so far: 16300
[3.497s][warning][os,thread] Failed to start thread "Unknown thread" - pthread_create failed (EAGAIN) for attributes: stacksize: 1048576k, guardsize: 16k, detached.
[3.497s][warning][os,thread] Failed to start the native thread for java.lang.Thread "Thread-16354"
Exception in thread "main" java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached


数据洞察

在所有三个测试中的一致性突显了堆栈大小对可以创建的原生线程数量没有影响。相反,限制似乎是由操作系统施加的。

值得注意的是,由于虚拟内存的概念,操作系统能够比可用物理内存更多地创建线程。虚拟内存利用磁盘空间来扩展RAM,允许应用程序分配比实际物理内存更多的内存,尽管访问速度较慢。

结论

与普遍的看法相反,这个实验证明了堆栈大小对可以在JVM环境中创建的原生线程数量没有影响。

这一限制主要由操作系统设定。这个调查有效地驱散了堆栈大小是原生线程限制的决定因素的迷思。

感谢您阅读本文。如果您对这个主题有不同的看法,或者如果您的实验得出了不同的结果,我会非常感兴趣听取。请随时与我分享您的发现。

别忘了分享这篇文章!

推荐阅读: 百度面经(2)

本文链接: 探讨堆栈大小对JVM线程创建的影响:揭秘一个神话