JAVA多线程,内存泄漏,垃圾收集器

Sim*_*lls 3 java multithreading garbage-collection

对于JAVA应用程序,我还是个新手,但是参与了开发一个需要多线程的相当复杂的JAVA(8)应用程序。我自己和另一个开发人员一直遇到一个问题,该应用程序在运行一段时间后仍会耗尽内存。

最初,我们为应用程序提供了64GB的内存,但是几个小时后,它的内存不足,崩溃并重新启动。只是一遍又一遍地做下去。上下文;该应用程序从消息传递系统(ActiveMQ)接收消息,并且必须通过调用各种数据源以获取值来从消息的meta中构建XML文件。从字面上看,可能需要处理数百万条消息,因此我们开发了一个多线程系统,每个线程处理一条消息,并为应用程序提供40个线程。

但是,由于它不断接收消息,因此总体内存消耗随着时间的推移而增加。我觉得垃圾回收器没有被我们正确地利用?

因此,目前我们有一个父线程:

(new Thread(new ReportMessageConsumer(config, ""))).start();

然后在ReportMessageConsumer中,我们有X个线程设置,因此在当前设置中为40个。因此,这将属于这一组。构建完XML并完成线程处理后,我们如何有效地杀死该线程并强制垃圾回收器释放该内存,以便我们随后可以创建一个新的干净线程来接收另一条消息?

Ste*_*n C 5

我觉得垃圾回收器没有被我们正确地利用?

那不是问题。您可以做的最好的事情就是让GC做到无干扰。不要试图强制GC运行。它很少有用,并且通常对性能不利。

真正的问题是您有内存泄漏。这可能是因为您获得了越来越多的线程而发生的……或者可能是其他原因。

我建议以下内容:

  1. 重写您的代码,以便它使用a ExecutorService来管理有限的线程池,以及在这些线程上运行的任务队列。查看javadocs中的一个简单示例。

    使用线程池可能会提高应用程序的整体性能。Thread.start()在Java中创建线程(即)相当昂贵。

    (并且不要关闭池,以确保完成一批工作。这对性能不利。执行此操作的简单方法是使用提交批处理invokeAll;请参阅ExecutorService,如何等待所有任务完成。)

  2. 如果那不能解决您的泄漏问题,请使用内存分析工具来找出您的应用程序如何/为什么泄漏内存。关于如何执行此操作,有很多StackOverflow问答。例如: