这是缓解内存不足错误的好方法吗



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

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

那么,以下是解决内存不足问题的有效方法吗?

在主线程中,检查可用内存的百分比,如果内存使用率超过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);
     }
}

有好的练习吗?

您应该用正确的设计而不是黑客来解决OOME问题。您的JSON对象应该被推送到一个有界的阻塞队列中,该队列将自动负责对生产者应用"背压"。

一个更干净的选择是重新设计,这样每个提交的任务都会得到加载的JSON的一部分来处理,这样它就不会自己提取任何东西。这样,您甚至不需要实现队列:您依赖于Executor Service内部的队列,只需要对其进行适当配置即可。例如,使用显式ThreadPoolExecutor构造函数,将CallerRunsPolicy作为拒绝策略传递给它。

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

否-这是个坏主意。

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

这里有一个帖子看起来很有希望。它自称是BoundedExecutor

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

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

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

我认为你有两种方法来解决这个问题:

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

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

如果你为他们提供了你需要的内存量的合理估计,他们应该是合理的(是的,我一生中遇到过困难的运算符:p)

最新更新