在 4GB iMac OSX 10.6.3 Snow Leopard(32 位)上无法通过 Java 中的 2542 个线程
Posted
技术标签:
【中文标题】在 4GB iMac OSX 10.6.3 Snow Leopard(32 位)上无法通过 Java 中的 2542 个线程【英文标题】:Can't get past 2542 Threads in Java on 4GB iMac OSX 10.6.3 Snow Leopard (32bit) 【发布时间】:2011-02-21 02:22:22 【问题描述】:我正在运行以下程序,试图弄清楚如何配置我的 JVM 以获得我的机器可以支持的最大线程数。对于那些可能不知道的人,Snow Leopard 附带 Java 6。
我尝试使用默认值和以下命令行启动它,无论 JVM 选项设置为什么,我总是在线程 2542 处出现内存不足错误。
java TestThreadStackSizes 100000
java -Xss1024 TestThreadStackSizes 100000
java -Xmx128m -Xss1024 TestThreadStackSizes 100000
java -Xmx2048m -Xss1024 TestThreadStackSizes 100000
java -Xmx2048m -Xms2048m -Xss1024 TestThreadStackSizes 100000
无论我通过什么,我都会得到相同的结果,Out of Memory Error at 2542
public class TestThreadStackSizes
public static void main(final String[] args)
Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
public void uncaughtException(final Thread t, final Throwable e)
System.err.println(e.getMessage());
System.exit(1);
);
int numThreads = 1000;
if (args.length == 1)
numThreads = Integer.parseInt(args[0]);
for (int i = 0; i < numThreads; i++)
try
Thread t = new Thread(new SleeperThread(i));
t.start();
catch (final OutOfMemoryError e)
throw new RuntimeException(String.format("Out of Memory Error on Thread %d", i), e);
private static class SleeperThread implements Runnable
private final int i;
private SleeperThread(final int i)
this.i = i;
public void run()
try
System.out.format("Thread %d about to sleep\n", this.i);
Thread.sleep(1000 * 60 * 60);
catch (final InterruptedException e)
throw new RuntimeException(e);
关于如何影响这些结果的任何想法?
我编写这个程序是为了弄清楚 Windows Server 2003 的能力,因为我得到这些out of memory can't create native threads
的数量非常少,比如几百个。我需要看看一个特定的盒子能用不同的-Xss
参数做什么,然后我在 OSX 上遇到了这个任意限制。
【问题讨论】:
哇,你有多少个 CPU?您在任何时候都只能在 CPU 上运行一个线程(可能是两个)。其余的只是增加开销。如果你认为你需要这么多线程,也许需要重新设计。 谁说我“需要”这么多线程,我只是想知道限制以及如何更改它们。 @PeterLawrey:如果您正在处理 I/O 密集型的工作,例如网络服务器或类似的东西,您通常会有大量空闲的线程在 I/O 上被阻塞。 /O,但仍占用操作系统进程表中的一个插槽。这不一定是他们使用多少 CPU 的问题。 @AdrianPetrescu 确实如此,但是超过 1000 个线程时,即使它们只是阻塞 IO,它们也会开始增加大量负载。 "您在任何时候只能在 CPU 上运行一个线程(可能是两个)。其余的只是增加开销。"这不是真的。至少在 CPU 绑定任务之外的任何事情上都不是这样。对于 IO 绑定任务,您可以拥有数倍于 CPU 的线程数而不会出现任何问题。 【参考方案1】:您需要找出操作系统在您的系统上支持的最大线程数。
在 linux 上,您可以执行以下操作:
cat /proc/sys/kernel/threads-max
要获得最大值并设置它,您可以执行以下操作:
echo 10000 > /proc/sys/kernel/threads-max
也尝试运行:
-XX:-UseBoundThreads
并报告结果。
【讨论】:
nope not on linux and -XX:-UseBoundThreads 不会改变任何东西【参考方案2】:根据Apple Developer doc,线程堆栈大小应至少为 64K,因此您的 -Xss 1014 将被忽略。但是即使每个线程有 64K,线程堆栈内存消耗也只有 160MB 左右,所以这应该不是问题。线程也可能从更有限的池中消耗内存,或者可能只是限制每个进程或用户可以拥有的线程数。
【讨论】:
我将它设置为 256k,但它仍然在完全相同的线程数下失败。 java -Xss256k -XX:ThreadStackSize=256 TestThreadStackSizes 10000【参考方案3】:2542 似乎是一个任意数字:
我关闭了所有程序,除了我运行测试的一个终端窗口,我到达2545
,告诉我这是一个任意限制。
要获取 OSX 10.6.3 的线程数,请执行以下操作:
> sysctl kern.num_threads
kern.num_threads: 2560
和
> sysctl kern.num_taskthreads
kern.num_taskthreads: 2560
2560
数字与2542
和2545
匹配,因为后台显然有其他线程在运行。
根据官方文档kern.num_taskthreads
在OSX桌面版中无法调整。
【讨论】:
在 OS X 10.8 和 10.11 上测试 'sysctl kern.num_threads' 数字显示为 10240。它似乎已经增加了。 @JasonFuerstenberg 在 10.11.5 上对我来说相同的数字,但是sysctl kern.num_taskthreads
给出 2048,我不能在 Java 中创建超过 2023 个线程。
@ErwinBolwidt jvm self也需要创建线程,添加2023就是2048,可以jstack这个进程查看一下。【参考方案4】:
你认为你会在长达 1 小时的时间内同时处理这么多线程吗?我不这么认为。我曾在处理数百个文档的应用程序中工作,将它们从差异转换为差异。格式,在数据库中生成正确的日志并存储特定信息。然后它也在几秒钟内完成。
你应该注意的事情是,明智地编码以避免产生过多的线程。而是使用 Java 提供的ThreadPool
,以便在需要时可以使用相同的线程。这将提供更好的性能。还要在最小块上保持同步以避免执行中的瓶颈。
谢谢。
【讨论】:
以上是关于在 4GB iMac OSX 10.6.3 Snow Leopard(32 位)上无法通过 Java 中的 2542 个线程的主要内容,如果未能解决你的问题,请参考以下文章
iMac 上的 XAMPP - 它会对内置的 Apache、Perl、PHP 产生不利影响