2016-06-30 9 views
1

私は、Javaアプリケーションに関しては初心者ですが、マルチスレッドを必要とするかなり複雑なJAVA(8)アプリケーションの開発に携わっています。自分自身と別の開発者は、しばらくの間実行した後にアプリがメモリ不足に陥る問題に苦しんでいる。JAVAマルチスレッド、メモリリーク、ガベージコレクタ

最初にアプリケーションに64GBのメモリを割り当てましたが、数時間後にメモリが不足してクラッシュして再起動しました。それだけ何度も何度もやり続けること。コンテキスト;アプリケーションはメッセージングシステム(ActiveMQ)からメッセージを受け取り、メッセージのメタから、値のさまざまなデータソースを呼び出してXMLファイルを構築する必要があります。文字通り何百万ものメッセージが処理される必要があります。そのため、マルチスレッドシステムを開発しました。各スレッドはメッセージを処理し、アプリケーションに40スレッドを与えました。

しかし、メッセージを受け取り続けるにつれて、全体的なメモリ消費量は時間の経過とともに上昇します。ガベージコレクターが正しく利用されていないような気がしますか?

ので、現時点では、我々は1つの親スレッドを持っている:

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

はその後ReportMessageConsumer以内に、我々は、スレッドのセットアップのX番号を持っているので、これは私たちの現在の設定で40になります。だから、これはこのグループの下にすべてあります。 XMLが構築され、スレッドがどのようにしてスレッドを効果的に削除し、そのメモリを解放するようにガベージコレクタを強制すると、新しいクリーンスレッドを作成して別のメッセージを受け取ることができますか?

+0

スレッドがまもなくその 'ラン()'メソッド戻りまたは例外をスローのいずれかの後に死にます。あなたのコードが 'Thread'オブジェクトへの参照を保持しておらず(あなたの例では明らかにそれを保持していない場合)、' Thread'オブジェクトとスレッドのスタックによって参照されるすべてのオブジェクトはすぐに再利用可能になりますGCによって。 –

+2

もしあなたが1つを殺し、別のメッセージを "別のメッセージ"を処理するために開始したいのであれば、スレッドを直接使用しないでください:executorを使用してください。 –

+0

正確なOutOfMemoryErrorは何ですか?ヒープ、スタック、GCオーバーヘッド、ネイティブスレッドを作成できないのですか? –

答えて

3

ガベージコレクタが正しく利用されていないような気がしますか?

これは問題ではありません。あなたができる最良のことは、GCが何の干渉もなくそのことを行うことです。 GCを強制的に実行しないでください。めったに役に立たず、の場合はが悪いことがよくあります。

本当の問題は、メモリリークがあることです。それは、あなたがますますスレッドを増やしているために起きているかもしれません。それは他のものかもしれません。

は、私は、次のをお勧めします:

  1. 書き換えあなたのコードを、スレッドの有界プールを管理するためにExecutorServiceを使用して、タスクのキューがそれらのスレッドで実行するようにします。簡単な例についてはjavadocsを見てください。

    スレッドプールを使用することは、アプリケーションのパフォーマンスを向上させるものではありません。スレッドを作成すると(つまり、Thread.start())、Javaではかなり高価です。

  2. メモリリークを解決できない場合は、メモリプロファイリングツールを使用して、アプリケーションにメモリがどのようにリークしているかを確認してください。これを行う方法については、多くのStackOverflow Q &があります。例えば:

+0

ありがとうございます。 'executorService =(ThreadPoolExecutor) Executors.newFixedThreadPool(maxThread); while(true){ if(executorService.getActiveCount()

+1

ExecutorServiceのようなスレッドプールには、キューによってバックアップされた固定数のスレッドが必要です。したがって、スレッドプールに10個のスレッドを割り当てると、それ以上のスレッドはありませんが、すべてのスレッドがビジー状態の場合、 'processMessage'は最終的な実行のためにキューに入れられます。言い換えれば、 'getActiveCount'やスレッド管理について心配する必要はありません –

+0

ありがとう、それは事をより簡単にします! その時点でまだメモリリークが発生しているのであれば、executorService内の何かがまだメモリに格納されているからです。私はexecutorService.shutdown()を呼び出すと、処理された各メッセージの最後に、GCを使用してすべてのメッセージが空になるはずですか? –