ExecutorService並列処理タスクの作成によりメモリ不足
2021 ワード
ExecutorServiceで作成したスレッドプールを使用してタスクを並列に処理することで、合計待ち時間(合計待ち時間は、最も多くの時間を費やしたタスクの時間と同じ)を節約できます.ただし、スレッドプールは自動的に解放されません.したがって、スレッドプールを1回作成した後に繰り返し使用するか、使用が完了するたびに明示的に解放されます.そうでないと、メモリが最終的に使用されなくなります.
問題:
Executorsを使用してスレッドプールの一括並列処理タスク(外部インタフェースの要求など)を作成し、しばらくするとjvmがOutOfMemoryエラーを報告し、プロセスが死んでしまいます.
jstackでスレッド数を観察すると、いくつかのタイプのスレッドが成長しています.
jstack | grep "waiting on condition"| wc -l
jstack | grep "waiting on condition"| grep pool |wc -l
問題コード(batchProcessは絶えず呼び出されます):
理由:executorServiceは明示的に閉じられず、スレッドプールが作成された後も新しいタスクを待っていたため、蓄積が多くなりました.
修正後のコード:
または:共通の
executorServiceは、すべての一括タスクで使用されるように、常に存在させます.
問題:
Executorsを使用してスレッドプールの一括並列処理タスク(外部インタフェースの要求など)を作成し、しばらくするとjvmがOutOfMemoryエラーを報告し、プロセスが死んでしまいます.
jstackでスレッド数を観察すると、いくつかのタイプのスレッドが成長しています.
jstack | grep "waiting on condition"| wc -l
jstack | grep "waiting on condition"| grep pool |wc -l
問題コード(batchProcessは絶えず呼び出されます):
private void batchProcess(List idList) throws Exception {
ExecutorService executorService = Executors.newFixedThreadPool(idList.size());
List taskList = new ArrayList<>();
for(Integer id : idList){
taskList.add(new AreaThread(id));
}
List> futureList = executorService.invokeAll(taskList);
List resultList = new ArrayList<>();
for(Future future : futureList){
Integer result = future.get();
logger.debug("result={}", result);
resultList.add(result);
}
}
理由:executorServiceは明示的に閉じられず、スレッドプールが作成された後も新しいタスクを待っていたため、蓄積が多くなりました.
修正後のコード:
private void batchProcess(List idList) throws Exception {
ExecutorService executorService = Executors.newFixedThreadPool(idList.size());
List taskList = new ArrayList<>();
for(Integer id : idList){
taskList.add(new AreaThread(id));
}
List> futureList = executorService.invokeAll(taskList);
List resultList = new ArrayList<>();
for(Future future : futureList){
Integer result = future.get();
logger.debug("result={}", result);
resultList.add(result);
}
executorService.shutdown(); // shutdown,
}
または:共通の
executorServiceは、すべての一括タスクで使用されるように、常に存在させます.