Java内存分配限制

时间:2009-12-13 18:57:23

标签: java limit heap-memory

我有一个产生很多线程的循环。这些线程包含2个(大量)StringBuilder对象。然后这些线程运行并完成它们的工作。

然而,我注意到经过一定数量的线程后,我发现了奇怪的崩溃。我知道这是因为这些StringBuilder,因为当我减少他们的初始容量时,我可以开始更多的线程。现在对于这些StringBuilders,它们在线程对象的构造函数中创建如下:

StringBuilder a = new StringBuilder(30000);
StringBuilder b = new StringBuilder(30000);

它通常崩溃的点是大约550个线程,这导致略多于62MB。结合程序的其余部分,使用的内存很可能是64MB,我在网上看到的是JVM内存分配池的默认大小。我不知道这是否属实。

现在,有什么我做错了,不知何故因为设计,我以错误的方式分配内存?或者这是唯一的方法,我应该告诉JVM增加其内存池吗?或完全不同的东西?

另外,请不要告诉我设置较低的容量,我知道这些StringBuilders会在需要时自动增加容量,但我想解决这个问题。

6 个答案:

答案 0 :(得分:5)

答案 1 :(得分:3)

如果要在StringBuilder中存储大量信息,是否要在某些时候引用它?如果没有,那么只需将其写入另一个媒体(DB,文件等)。该程序具有有限的资源,它不能同时保持整个系统的所有状态。 -Xmx将为您提供更多存储空间,但不会使您的存储能力无限。

答案 2 :(得分:2)

考虑使用ThreadPoolExecutor,并将池大小设置为计算机上的CPU数。创建比CPU更多的线程只会增加开销。

ExecutorService service = Executors.newFixedThreadPool(cpuCount))

此外,您可以通过将字符串写入文件来减少内存使用量,而不是使用StringBuilder将其保留在内存中。

答案 3 :(得分:1)

假设每个线程1MB。这是创建每个内存的RAM成本,超过其进程分配的内存。

答案 4 :(得分:1)

正如格雷戈里所说,给jvm一些选项,比如-Xmx。

还要考虑使用ThreadPool或Executor来确保只有一定数量的线程同时运行。这样可以保持内存量不受限制(因为你的处理器无法同时运行550个线程)。

当你使用Executor时,不要在构造函数中创建StringBuilders,而是在run方法中。

答案 5 :(得分:0)

您可以使用FileWriter将文本输出到文件,然后使用FileReader将其重新插入。这样你只需要将文件名存储在内存中,而不是存储在字符串的全部内容中。

要减少线程,可以使用ExecutorService,或者只使用从队列中读出的几个线程。

我的猜测是,通过一点点的修补,你可能会让你的程序根本不需要太多的内存。