0

Java executor を使用していくつかのランナブルを実行する tomcat webapp があります。

まず、次のように、executor インスタンスから executor サービスを割り当てます。

executorService = Executors.newFixedThreadPool(nThreads, new MyThreadFactory(threadFactoryName))

次に、executor サービスを使用してタスクを起動します。

executorService.execute(new MyRunnable);

すると、うまくいくようです。しかし、私の問題は、サーバーをしばらく実行した後にこのエラーが発生する何らかのリークを追跡していることです。

Caused by: java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:640)
at java.util.concurrent.ThreadPoolExecutor.addIfUnderCorePoolSize(ThreadPoolExecutor.java:703)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:652)
at something.server.ThreadExecutor.execute(MyRunnable.java:91)

Tomcat インスタンスで Java VisualVM を使用して、スレッドの割り当てを追跡しました。「newFixedThreadPool」を呼び出すと、「nThreads」の新しいスレッドが表示されます。しかし、彼らの仕事が終わった後、スレッドの状態が「待機中」になっていることがわかります。

それは正常ですか?ランナブルが仕事を終えることは知っていますが、エグゼキューターサービスはスレッドを決して解放しません。それらを解放するにはどうすればよいですか、それとも完全に範囲外ですか?

4

3 に答える 3

4

ExecutorServiceリクエストごとに新しいものをインスタンス化しているか、そのようなものだと思います。

を 1 つだけインスタンス化して再利用するか、タスクの送信が完了した後にサービスをExecutorService呼び出す必要があります。shutdown()関数はタスクが終了するのshutdownを待ってから、スレッドを解放します。

于 2012-12-13T22:15:09.493 に答える
2

それは正常ですか?ランナブルが仕事を終えることは知っていますが、エグゼキューターサービスはスレッドを決して解放しません。

はい、正常です。実際、新しいスレッドの作成はコストのかかる操作であるため、この動作は望ましいものです。プール スレッド (または少なくとも「コア」プール スレッド) は、executor がシャットダウンされるまで存在し続けます。

それらを解放するにはどうすればよいですか、それとも完全に範囲外ですか?

スレッド プールを構成して、「コア」スレッド プールを小さくしたり、keepAlive 時間を小さくしたりできるはずです。詳細については、javadocを参照してください。


[私の]問題は、サーバーをしばらく実行した後にこのエラーが発生する、ある種のリークを追跡していることです。

その OOME は、必ずしもリークを示しているわけではありません。作成しようとしているスレッドの数に対して十分な非ヒープ メモリが残っていないことを示している可能性があります。(または別の言い方をすれば、スレッドプールが大きすぎるということです。)

于 2012-12-13T22:13:32.537 に答える
2

固定スレッド プールをインスタンス化しています。またはを呼び出して を終了するまで、ExecutorServiceはスレッドを解放しません。ExecutorServiceExecutorService.shutdown()ExecutorService.shutdownNow()

于 2012-12-13T22:15:02.737 に答える