64 位 Linux 上的 Java 线程堆栈大小
Posted
技术标签:
【中文标题】64 位 Linux 上的 Java 线程堆栈大小【英文标题】:Java thread stack size on 64-bit linux 【发布时间】:2011-10-18 21:07:04 【问题描述】:我的目标是提出可以并行运行的最大线程数。谷歌向我指出了许多链接,它们通过划分 RAM/StackSize 给出了简单的数学计算。在 64 位 Linux 中,我们将线程堆栈大小定义为 10 MB(ulimit -s = 10240kb),RAM 为 4GB,为操作系统留出 1 GB 空间,根据这个数学计算,我可以拥有大约 300 个线程,但我的测试应用程序很小写到〜32297,然后给出内存不足错误。
我用 -Xss 尝试了不同的值,但这些值对线程数几乎没有任何影响,它仍然与 ~32297 相同)。
这给我的印象是堆栈大小是可变的,由操作系统决定,并在需要时达到我们定义的最大值,但无论我在哪里阅读,它们的堆栈大小都是静态的
我到底错过了什么?
【问题讨论】:
你可能会被内核限制为mentioned here 您可以拥有与处理器或内核一样多的线程来真正并行运行。否则,JVM 调度程序会随意交错它们。 @Joachim :我读了这篇文章,谢谢..你能否建议我的情况是线程最大变量(其值为 81920)背后的决定因素,堆栈大小为 10 MB,RAM 为 4国标。无法通过数学计算得到这些数字 ***.com/questions/34452302/… - 完成所有这些检查后解决了我的问题。 【参考方案1】:这是因为 pid_max 内核变量默认为 32768,但对于 64 位系统,可能会增加到 4 百万。 解释很简单 1 个线程 = 1 个进程,它将有 1 个 PID(进程 ID),所以没有更多的 pid,没有更多的线程。
【讨论】:
【参考方案2】:Linux 间接实现了每个进程的最大线程数!!
number of threads = total virtual memory / (stack size*1024*1024)
因此,可以通过增加总虚拟内存或减少堆栈大小来增加每个进程的线程数。但是,在最大虚拟内存等于交换内存的情况下,过多地减小堆栈大小会导致堆栈溢出导致代码失败。
检查你的机器:
总虚拟内存:ulimit -v
(默认为无限制,因此您需要增加交换内存来增加)
总堆栈大小:ulimit -s
(默认为 8Mb)
增加这些值的命令:
ulimit -s newvalue
ulimit -v newvalue
*将新值替换为您要设置为限制的值。
参考资料:
http://dustycodes.wordpress.com/2012/02/09/increasing-number-of-threads-per-process/
【讨论】:
【参考方案3】:我还发现 Java 中线程的限制约为 32K。如果你有这么多线程,使用不同的方法通常是一个更好的主意。在我的机器上执行 while(true) Thread.sleep(1000)
的 32K 线程将消耗 3 个内核,只是上下文切换。
Java: What is the limit to the number of threads you can create?
【讨论】:
在您分享的链接中,他们提到了 64 位,堆栈大小为 128K,限制为 32,072,堆栈大小为 512K,限制再次为 32,072。你知道为什么堆栈大小对可以创建的线程数没有任何影响吗?【参考方案4】:尝试使用检查/更改 linux 最大堆栈大小
ulimit -s
同时检查 linux 线程限制
cat /proc/sys/kernel/threads-max
【讨论】:
cat /proc/sys/kernel/threads-max 是 81920 。我想知道 b/w ulimit -s 和 threads-max 的关系,如果我更改堆栈大小,threads-max 值会更新吗?【参考方案5】:当限制为地址空间 (2^32) 时,您所阅读的内容仅在 32 位架构中有效。你实际上有这样的东西:Xmx + MaxPermSize + (Xss * 线程数)
对于 64 位架构,您的地址空间不会是限制 (2^64)。您应该像上面所说的那样查看操作系统限制。
【讨论】:
很好,仍然没有答案的问题是,为什么即使将堆栈大小更改为非常大或非常小的值,最大线程数仍保持不变。操作系统是否动态选择堆栈大小?以上是关于64 位 Linux 上的 Java 线程堆栈大小的主要内容,如果未能解决你的问题,请参考以下文章
BackgroundWorker DoWork 线程的堆栈大小是多少?有没有办法改变它?