23

私のWebアプリでは、ExecutorService固定サイズのThreadPoolを使用するサービスを作成しました。ExecutorService私はアプリケーションの存続期間全体にわたって同じものを再利用します。

private static ExecutorService pool = Executors.newFixedThreadPool(8);

すべてがTomcatで実行されているため、シャットダウン中に次のエラーが発生します。

appears to have started a thread named [pool-1-thread-1] but has failed to stop it. This is very likely to create a memory leak.

私は、Tomcatをシャットダウンする前にExecutorServiceをシャットダウンする必要があることを認識しています。Soms SOスレッドはすでにこれについて話しますが、これを処理するためのクリーンな方法を見つけることができませんでした。

スレッドとエグゼキュータのグレースフルシャットダウンでShutdownHook、提案された@ Tim-benderを使用する必要がありますか?または、代わりにCachedThreadPoolを使用する必要がありますか?

4

2 に答える 2

25

シャットダウンフックは、Tomcatでは適切なアプローチではありません。理由は次のとおりです。

  • プールを閉じるのが遅すぎます(シャットダウン時)。Tomcatはすでにリソースが閉じられていないことを警告します

  • アプリケーションがアンデプロイされたときに実際にそのプールをシャットダウンして、再デプロイが機能するようにします(そうしないと、各アプリケーションが新しいプールを作成し、完全にシャットダウンした場合にのみすべてが閉じられます)

  • スレッドプールのシャットダウンには時間がかかる場合があります(以下を参照)。シャットダウンフックはできるだけ速くする必要があります

はるかに良い場所ですServletContextListener.contextDestroyed()shutdownNow()プール(実行をキャンセルして新しいタスクを拒否するため)とawaitTermination()、すでに実行中のタスクが終了してすべてのスレッドが停止するのを待つ必要があることを忘れないでください。

于 2012-10-10T09:02:03.677 に答える
7

Tomaszが提案したことに加えて、CachedThreadPoolを使用することもできます

60秒間使用されなかったスレッドは終了し、キャッシュから削除されます。したがって、十分長い間アイドル状態のままであるプールは、リソースを消費しません。

したがって、非常に優れた解決策は、で使用CachedThreadPoolしてシャットダウンすることですServletContextListener.contextDestroyed()

于 2012-10-10T09:14:12.733 に答える