这是减轻OutOfMemoryError的好习惯吗?

时间:2013-12-05 09:27:17

标签: java memory-management out-of-memory

考虑一个java进程,主线程从源读取Json对象,并将具有读取Json对象的任务分配给具有5个工作线程的FixedThreadPoolExecutor。

问题在于,从中读取Jsons的源比工作线程完成任务要快得多。因此,当Jsons在内存中等待工作线程时,会抛出OutOfMemoryException。这里不能增加工作线程数。

以下是OutOfMemory问题的有效解决方案吗?

在主线程中检查可用内存的百分比并在内存使用率超过80%时休眠一段时间

main(){
    for(;;){
       //read the data and assign to executor
      long total = Runtime.getRuntime().maxMemory(),free = Runtime.getRuntime().freeMemory()
      float usedPersent = (total-free)*100/total
      if(usedPercent > 80)
         Thread.sleep(2000);
     }
}

有没有好的做法?

5 个答案:

答案 0 :(得分:4)

你应该用适当的设计而不是黑客来解决你的OOME问题。您的JSON对象应该被推入一个有界的阻塞队列,这将自动处理对生产者应用“背压”。

更清晰的选择是重新设计,以便为每个提交的任务提供一部分加载的JSON来处理,因此它不会自行提取任何内容。这样您甚至不需要实现队列:您依赖Executor Service内部的队列,您只需要适当地配置它。例如,使用显式ThreadPoolExecutor构造函数,将CallerRunsPolicy作为拒绝策略传递给它。

另请注意,提前加载过多的JSON会降低整个系统的速度,因为多余的对象将被提升为旧一代,从而增加主要垃圾收集的频率。

答案 1 :(得分:1)

不 - 这是一个坏主意。

您应该创建具有最大池大小和有限长度队列大小的线程池,并正确处理拒绝。

有一篇看似有希望的帖子here。它声称是BoundedExecutor

答案 2 :(得分:1)

不,这不是一个坏主意。据我所知,在发生OutOfMEmoryException之后根本没有指定JVM的行为(抱歉,我现在没有链接)。在某些情况下,您甚至可能看不到此异常。因此,监控JVM堆使用情况至关重要,例如在服务器环境中。

答案 3 :(得分:0)

一个更好的解决方案可能是一个在它满时阻塞的队列。这样,您可以保持积压的可管理性,而不会通过Thread.sleep进行线程同步。

答案 4 :(得分:0)

我不确定这个想法。主线程从哪里检索其工作?是不是让客户在这2秒内保持睡眠和等待?

我认为你有2种方法可以解决这个问题:

  • 您认为您有什么方法可以提高数据处理的效率吗?也许如果你能让你的工作线程更好地运行,他们可以比现在更快地减轻你系统的负担
  • 或者,如果您确定无法获得更好的性能,那么您的操作可能是真正的资源问题,应该询问您的运营商或管理生产系统的任何人使用不同的堆大小进行不同的JVM设置。看看

http://www.jafaloo.com/java-xmx-memory-settings/

如果你向他们提供你需要的记忆量的合理估计,那么它们应该是合理的(是的,我在生活中对待过艰难的操作员:P)