3

我有一种情况,我需要从第三方 API 创建数千个类的实例。每个新实例都会创建一个新线程。一旦线程数超过 1000,我就会开始出现 OutOfMemoryError。但我的应用程序需要创建 30,000 个实例。每个实例始终处于活动状态。该应用程序部署在具有 8GB RAM 的 64 位 linux 机器上,我的应用程序只有 2GB 可用。

第三方库的工作方式,我不能使用新的 Executor 框架或线程池。

那么我该如何解决这个问题呢?

请注意,使用线程池不是一种选择。所有线程一直在运行以捕获事件。

linux 机器上的正弦内存大小不在我的控制范围内,但如果我可以选择在 32GB 系统中为我的应用程序提供 25GB 可用空间,那会解决我的问题还是 JVM 仍然会阻塞?

上述场景是否有一些最佳的 Java 设置?

系统使用 Oracle Java 1.6 64 位。

4

4 回答 4

7

我会说现在放弃并想出另一种方法来做到这一点。默认堆栈大小为 512K。在 30k 线程时,仅堆栈空间就有 15G。为了适应 2G,您需要将其减少到少于 64K 的堆栈,这使您的堆内存为零,包括所有 Thread 对象或 JVM 本身。

这只是在一个 JVM 中同时运行这么多线程时可能遇到的最明显的问题。

于 2013-08-16T00:09:22.780 回答
7

I concur with Ryan's Answer. But the problem is worse than his analysis suggests.

Hotspot JVMs have a hard-wired minimum stack size - 128k for Java 6 and 160k for Java 7.

That means that even if you set the stack size to the smallest possible value, you'd need to use roughly twice your allocated space ... just for thread stacks.

In addition, having 30k native threads is liable to cause problems on some operating systems.

I put it to you that your task is impossible. You need to find an alternative design that does not require you to have 30k threads simultaneously. Alternatively, you need a much larger machine to run the application.


Reference: http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2012-June/003867.html

于 2013-08-16T00:48:24.277 回答
1

我认为我们遗漏了很多细节,但是分布式平台会起作用吗?每个单独的实例都将管理您的一系列类实例。这些平台可以在不同的电脑或虚拟机上运行并相互通信?

于 2013-08-16T00:32:30.387 回答
1

我对一个 SNMP 提供程序有同样的问题,它需要一个线程来处理每个未完成的获取(我希望一次有数万个未完成的获取)。现在 NIO 存在,如果我不得不再次这样做,我只会自己重写库。

您无法在“Java 代码”或配置中解决它。根据我的经验,Windows 会在大约 2-3000 个线程时阻塞(这可能在以后的版本中有所改变)。当我这样做时,我惊讶地发现 Linux 支持的线程更少(大约 1000 个)。

当系统停止提供线程时,“内存不足”是您应该期望看到的异常——所以我确定就是这样——我在内存不足之前很久就开始得到这个异常。也许你可以以某种方式破解 linux 以支持更多,但我不知道如何。

在这里使用并发包将无济于事。如果您可以切换到“绿色”线程,它可能会,但这可能需要重新编译 JVM(如果它可以作为命令行开关使用会很好,但我真的不这么认为)。

于 2013-08-16T00:38:34.647 回答