我有一個基於JSP的(Java)Web應用程序。在這個應用程序中,我可以通過執行外部命令,向機器(PC)詢問他們的狀態和基於他們IP的實際操作系統。ExecutorService和OutOfMemoryError:無法使用執行程序創建新的本機線程
爲了加速請求,我想用線程同時詢問更多的機器,即ExecutorService。
相應視圖的preRenderView偵聽器設置爲此方法,我收集所有必須顯示的數據。在這裏,我初始化執行,這被聲明爲私有靜態類字段(private static ExecutorService executor
):
public void selectData(ComponentSystemEvent event)
{
AmtRoomMachinesListController.executor = Executors.newFixedThreadPool(20);
AmtRoomMachinesListModel amtRoomMachinesListModel = (AmtRoomMachinesListModel)getModel();
List<ListRow> listRows = fetchListRows(amtRoomMachinesListModel);
...
}
在fetchListRow
執行人被調用,並提交調用。然後執行程序已關閉和終止:
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;
}
我的問題是,進程數/線程不斷增加,經過一段時間後,我得到了內存不足的異常。每調用一次selectData
,進程數就會增加提示機器的數量。
我是線程的新手,但我認爲執行程序會在調用executor.shutdown()或executor.awaitTermination或executor.purge()時通過終止/殺死它們來處理生成的線程。
我錯過了什麼?
創建爲每個請求新執行的嫌疑。您可能應該創建一個執行程序並將其用於所有請求。 – OldCurmudgeon
執行器完成後,您是否嘗試將引用置零?除此之外,我第二@OldCurmudgeon。您可能應該創建一個「全局」ExecutorService並使用[InvokeAll](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#invokeAll-java.util.Collection - 長-java.util.concurrent.TimeUnit-)。 – Fildor
您的代碼中有日誌記錄語句。日誌顯示了什麼?等待 - 顯然,你的'executor'是你的類中的一個靜態變量,你可以從實例方法中使用它。這是要求混亂。每次調用selectData時,該變量都會被覆蓋,即使其他對象仍在使用它。所以你無法控制哪個執行器會關閉(或多久),哪個永遠不會關閉。 – Holger