【问题标题】:Using a concurrent hashmap to reduce memory usage with threadpool?使用并发哈希图来减少线程池的内存使用?
【发布时间】:2011-08-31 14:51:36
【问题描述】:

我正在使用一个运行冗长的 SQL 查询并将处理后的结果存储在 HashMap 中的程序。目前,为了解决每个 20-200 个查询的缓慢执行时间,我使用一个固定的线程池和一个自定义的可调用来进行搜索。因此,每个可调用对象都会创建数据的本地副本,然后将其返回到主程序以包含在报告中。

我注意到过去运行没有问题的 100 个查询报告现在导致我内存不足。我的猜测是,因为这些可调用对象正在创建自己的数据副本,所以当我将它们加入另一个大型 HashMap 时,内存使用量会增加一倍。我意识到我可以尝试通过缩小可调用表的范围来哄骗垃圾收集器运行,但是如果可以避免的话,这种级别的重组并不是我真正想要做的。

我是否可以通过将可调用对象替换为可运行对象而不是存储数据,将其写入并发 HashMap 来提高内存使用率?还是听起来我这里有其他问题?

【问题讨论】:

  • 我想我可能已经找到了一种更简单的方法来削减它,但我仍然对如上所述的进一步优化非常感兴趣。我注意到,当我编写报告时,我的 xml 编写器创建了一个包含另一个地图副本的文件。通过在将映射条目写入文件时删除它们,我应该能够减少更多。有趣的是,这样的小事竟然会溜走。

标签: java memory-management hashmap threadpool concurrenthashmap


【解决方案1】:

不要创建数据副本,只需传递引用,确保线程安全(如果需要)。如果没有数据复制,您仍然有 OOM,请考虑增加应用程序的最大可用堆。

上述不使用数据副本的方法的缺点是线程安全更难实现。

【讨论】:

  • 我同意。 @William 没有说明为什么他的自定义 Callable 会返回检索到的数据的副本,但这似乎很奇怪。
  • 由于他使用的是 Callable,因此没有同步需要处理。
【解决方案2】:

您真的需要同时提供所有 100-200 份报告吗?

是否值得将第一级缓存限制为仅 50 个报告并基于WeakHashMap 引入第二级缓存? 当第一级超过其大小时,LRU 将被推送到第二级,这取决于可用内存的数量(使用 WeakHashMap)。

然后要搜索报告,您首先需要查询 1 级,如果值不存在则查询 2 级,如果值不存在,则报告在内存不足时被 GC 回收,您必须再次查询 DB为这份报告。

【讨论】:

  • +1 向我介绍了另一种可能有用的数据结构。不过,我认为这不适用于这个项目。
【解决方案3】:

查询结果是否依赖于其他查询结果?如果没有,每当您在另一个线程中发现结果时,只需像您暗示的那样使用 ConcurrentHashMap 。您是否真的需要询问创建多个不必要的数据副本是否会导致您的程序内存不足?这应该是显而易见的。

【讨论】:

    猜你喜欢
    • 2012-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-19
    • 2012-02-06
    • 2012-12-02
    • 2013-05-21
    • 1970-01-01
    相关资源
    最近更新 更多