JSP上に(Java)Webアプリケーションベースがあります。このアプリケーションでは、外部コマンドを実行することによって、IPに基づいて状態(state)と実際のオペレーティングシステムについてマシン(PC)に問い合わせることができます。ExecutorServiceとOutOfMemoryError:Executorを使用している間に新しいネイティブスレッドを作成できません
リクエストを高速化するために、スレッドを使用して複数のマシン、つまりExecutorServiceを同時に要求すると考えました。
対応するViewのpreRenderViewリスナーがこのメソッドに設定され、ここで表示する必要があるすべてのデータを収集します。 executorが呼び出されると、呼び出し可能が提出されfetchListRow
で
public void selectData(ComponentSystemEvent event)
{
AmtRoomMachinesListController.executor = Executors.newFixedThreadPool(20);
AmtRoomMachinesListModel amtRoomMachinesListModel = (AmtRoomMachinesListModel)getModel();
List<ListRow> listRows = fetchListRows(amtRoomMachinesListModel);
...
}
:ここで私は、プライベート静的クラスフィールド(private static ExecutorService executor
)として宣言されたexecutorを、初期化します。その後、エグゼキュータは、シャットダウンして終了します:
private List<ListRow> fetchListRows(AmtRoomMachinesListModel amtRoomMachinesListModel)
{
...
List<ListRow> listRows = Collections.synchronizedList(new ArrayList<ListRow>());
for (Machine machine : room.getRoomPCs())
{
executor.submit(new AmtcWorker(listRows, machine, amtRoomMachinesListModel));
}
executor.shutdown();
try
{
executor.awaitTermination(20, TimeUnit.SECONDS);
}
catch (InterruptedException e)
{
throw new BootrobotException(ExceptionType.AMTC_ERROR, "command", "Waiting for thread termination", "error", e.getMessage());
}
((ThreadPoolExecutor)executor).purge();
LOGGER.info("Executor is shut down: " + executor.isShutdown());
LOGGER.info("Executor is terminated: " + executor.isTerminated());
sortListRows(listRows);
return listRows;
}
私の問題は、プロセス/スレッドの数は絶えず増加し、いくつかの時間後、私はのOutOfMemory例外を取得することです。 selectData
が呼び出されるたびに、プロンプトされたマシンの数だけプロセスの数が増えます。
私はスレッドを使用する新人ですが、executor.shutdown()またはexecutor.awaitTerminationまたはexecutor.purge()が呼び出されたときに、実行スレッドが生成スレッドを終了/強制終了することによってエグゼキュータが処理すると考えました。
私には何が欠けていますか?
をローカライズされた容疑者です。 1つのエグゼキュータを作成し、それをすべての要求に使用する必要があります。 – OldCurmudgeon
実行者の実行後に参照をnullにしてみましたか?それ以外では、私は2番目@OldCurmudgeon。おそらく、1つの「グローバル」ExecutorServiceを作成し、[InvokeAll](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#invokeAll-java.util.Collection)を使用する必要があります。 -long-java.util.concurrent.TimeUnit-)。 – Fildor
コードにロギングステートメントがあります。ログには何が表示されますか?ちょっと待ってください。あなたの 'executor'はインスタンスメソッドから使うクラスの' static'変数です。それは混乱を求めています。その変数は、 'selectData'が呼び出されるたびに上書きされます。他のオブジェクトがまだそれを使用していても変わりません。したがって、どのエグゼキュータがシャットダウン(またはどのくらいの頻度)されるのか、またどのエグゼクティブがシャットダウンされるのかは制御できません。 – Holger