2015-10-17 64 views
0

我有一個服務調用數據庫並對每個結果執行回調。執行器服務和巨大的IO

ExecutorService service = Executors.newFixedThreadPool(10); 
service.exectute(runnable(segmentID, callback)); // database is segmented 

Runnable的是:

call database - collect all the rows for the segment keep in memory 
perform callback(segment); 

現在的問題是,我得到數據庫返回了一個龐大的行,我的理解是執行服務將調度線程,每當他們在I/O閒置。所以我進入了內存不足。

有什麼辦法可以限制只有10個線程在同一時間運行,並且沒有執行器服務調度發生?

出於某種原因,我必須保持段中的所有行在內存中。 如何防止通過這樣做去OOM。 Executor服務是否爲此newFixedThreadPool解決方案?

請讓我知道,如果我錯過了什麼。

謝謝

+1

處理未知事物的一些未知代碼會導致內存問題。很難幫助。發佈您的代碼。告訴我們你如何「呼叫數據庫」。向我們展示回調的功能。 –

+0

請假設我想在可運行內部執行大量的IO,並將檢索到的值保存在內存中。如果我說10個線程在執行IO並且其他線程處於空閒狀態,那麼我不會去OOM,但是如果執行程序服務在執行IO時安排其他線程,那麼我肯定會進入OOM。 –

+0

如果向10個線程可用的執行程序提交10個任務或更多任務,則10個線程*將*同時執行。這就是整個問題。如果你只想並行執行2個線程,那麼用2個線程創建一個執行程序。但無論如何,即使任務完成後,所有內容都會保留在內存中,線程數量不會改變任何內容。 –

回答

1

您必須使用固定的線程池。有一條規則,你應該只產生N個線程,其中N應該與CPU的內核數量相同。關於N的大小有一個爭論,你可以閱讀更多關於它的文章here。對於一個普通的CPU,我們可以說4,8,16個線程。

但即使你在一個集羣中運行你的程序,我認爲你不是,你不能從數據庫中取出20k行並假裝產生20k個線程。如果這樣做,應用程序的性能會降低大部分時間,因爲大部分CPU週期將在上下文切換中消耗。

現在,即使使用固定線程池,如果獲取的數據同時存儲在內存中,也可能會遇到OOM異常。我認爲唯一的解決方案是獲取更小的數據塊,或者在數據下載時將數據寫入文件。

+0

感謝:) –