Java GC超过限制。有很多哈希映射和优先队列。我该怎么办?

3
我已经搜索了答案,但是没有找到完全可以回答我的问题的东西。 :D
所以,我需要从一个哈希映射表创建另外3个新的哈希映射表,用三种不同的方式交换其中2个值(我使用map2.putAll(map1)然后切换2个值),之后我必须将哈希映射表存储在有序的优先队列中,然后轮询其中一个并重复该过程。
问题是,由于特定条件未满足,我必须多次执行此操作...而且没有办法减少我所做的地图数量(好吧,我可能会阻止重复的地图,但这可能非常昂贵:/)。
实际上,我真的不介意如果我在某个地方存储了所有的地图(根据我读到的内容,我发现这是GC的错误),或者如果我必须进行其他技巧...我只想让我的代码能够工作,而不使用像“-XX:-UseGCOverheadLimit”这样的东西,因为这是一种作业(即使没有分数),而且它必须通过提示符的“java classname”运行。
唯一的限制是时间(这不是问题,我对此非常确定,已经测试过),它将被测试只用简单的输入(其中已经很好了),但我希望它能够处理更困难的输入。
我提前感谢您。
哦,地图是这样的:<Integer, Integer>,大小为 16 。不幸的是,我不能在这里发布代码,因为家庭作业尚未结束(即使我提交了我的) 。

1
当你的内存不足时,会发生GC超过限制的情况,但仍然有一点可以回收和继续执行。增加堆限制或修复应用程序以消耗更少的内存。 - Marko Topolnik
我想出来了...但我真的不知道该怎么做。也许我可以清除地图? - user1834153
好的,我会尝试将它们设置为null! - user1834153
这可能不会产生任何影响,但除此之外,您可以尝试调用 Thread.yield() 或甚至一些 Thread.sleep() 来减慢应用程序的速度,从而可以减少与 GC 所花费时间的比例。 - biziclop
我把HashMap改成了一个简单的int[]...现在它运行得非常好 O.o 为什么会发生这样的事情呢?我的意思是,我创建的对象是一样的...编译器在方法'addAll()'上抛出错误,为什么会发生这样的事情呢? - user1834153
显示剩余2条评论
3个回答

1
很难从描述中判断您的代码确切发生了什么,但如果分配和清除映射的内存开销是导致问题的原因,您可以缓存Map实例并重复使用它们。使用一些对象池实现,有很多选择,或者如果只有一个线程,则可以使用Stack作为对象池。另一个问题是使用Integer会导致大量的内存波动,而且由于Integer是不可变的,这有点痛苦。将您的Map替换为Trove int/int map即可解决 :)

0

HashMap在内存方面是昂贵的:只有在需要从大型数据集进行快速搜索时才使用它们。如果你的需求不需要Hashmaps,那么“并且大小为16”看起来就没有必要使用。


0

如果您能提供更多关于任务的具体信息,那么这可能会有所帮助……但是让我分享一下我的想法。

首先,使用 Integer(类)与 int(原始类型)应该不会有太大问题。它确实会使用更多的内存,但嘿,它仍然只是整数。除非你有大量的整数,否则不应遇到任何问题。HashMap 也是如此。相信社区。如果 HashMap 存在严重问题,我们早就发现了。

听起来像是您的程序存在内存泄漏。检查一下您的程序。您说您不想增加内存限制(如果您问我的话,这是明智的决定),但您可以尝试这个方法进行测试。如果您的程序存在内存泄漏,那么它将在出现相同问题之前运行得稍微长一些。有专门用于检测内存泄漏的工具,但只需使用标准的 Windows 进程管理器并随时关注程序的内存消耗情况即可快速发现是否存在内存泄漏。如果您的程序一遍又一遍地做着同样的事情,您应该期望内存消耗相对稳定。随着垃圾回收器再次分配和收集内存,它会随着时间的推移而上下波动,但这应该保持在一个相当稳定的带宽范围内。

如果你确信自己没有内存泄漏,那么你可能正在错误的方式下解决问题。例如,一个天真的文件处理实现可能会将文件读入内存,处理它,然后再保存回去...但是,如果文件大小为1GB,那么这种方法将消耗1GB的内存来存储加载的数据。如果需要处理大量的数据,则不要一次性处理它,而是分块处理。将文件数据的一部分读入缓冲区,处理它,丢弃已处理的数据并读取下一个块。这样,您的应用程序可以处理任何大小的文件。这只是一个例子,但这种问题通常与内存有关。要么你有一个泄漏,要么你的方法是错误的。只有那些处理大量数据的巨大程序才会达到内存限制。大多数程序都不是这样的。它们只是要么有内存泄漏,要么使用了错误的方法来解决问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接