2010-07-22 45 views
1

我在尋找一個java線程池,它不會同時運行比系統中的核心多的線程。此服務通常由使用BlockingQueue的ThreadPoolExecutor提供。但是,如果一個新線程被調度執行,我希望新線程搶先其中一個已經運行的線程,並將已被佔用的線程(處於掛起狀態)添加到任務隊列中,因此只要新線程完成就可以恢復。具有可預佔線程隊列的java執行程序

有什麼建議嗎?

+0

我認爲Java-Threads不能像那樣使用,因爲除非您自己實現這樣的方法,否則暫時停止然後繼續線程是不可能的。 但是沒有通用的方法來搶佔可運行,暫停執行並讓另一個線程繼續。事實上,從來沒有更多的線程運行*比系統中的內核數量更多。這是一個簡單的物理定律。如果您的系統中運行的線程數多於核心數,則java會自動調度正在運行的線程中的可用CPU(使用搶佔)。 – Javaguru 2010-07-22 09:52:49

+0

感謝您的回覆。 我知道Java中已經廢棄了線程掛起,但是還有其他方法,如以下所述:http://download.oracle.com/docs/cd/E17476_01/javase/1.4.2/docs/guide /misc/threadPrimitiveDeprecation.html。我已經實現了一個類似的方法來暫停我的線程。 我的目標是儘快完成「新」任務。 – TinkerTank 2010-07-22 10:02:30

回答

4

我會做一個ThreadPoolExecutor的子類。

當你設置你的ThreadPoolExecutor要設置corePoolSizemaximumPoolSizeRuntime.getRuntime().availableProcessors()(看Executors.newFixedThreadPool()明白爲什麼這個工程)。

接下來,您要確保Queue也執行DequeLinkedBlockingDeque就是一個例子,但你應該購物以查看哪一個最適合你。 A Deque允許您像LIFO行爲那樣獲取堆棧,這正是您想要的。

因爲一切(submit(),invokeAll())通過​​渠道,您將要覆蓋此方法。基本上做你上面描述的:

檢查是否所有線程都在運行。如果不是簡單地在可用線程上啓動新的runnable。如果所有線程都已經在運行,那麼您需要找到運行最早的可運行程序的那個線程,停止可運行程序,將可運行程序重新排列在某處(也許在開始處?),然後啓動新的可運行程序。

1

ThreadPoolExecutor的想法是爲了避免所有與創建和銷燬線程相關的昂貴操作。如果你絕對堅持搶佔正在運行的任務,那麼你將無法從默認的API中獲得。

如果您願意允許正在運行的任務完成,而只是搶佔尚未開始執行的任務,那麼您可以使用BlockingQueue實現,其工作方式與堆棧(LIFO)相似。

通過使用具有不同線程優先級的不同執行程序,您還可以讓任務「搶佔」其他任務。從本質上講,如果操作系統支持時間片,則較高優先級的執行者獲取時間片。

否則,您需要一個管理執行的自定義實現。您可以使用SynchronousQueue並讓P工作線程在其上等待。如果客戶端調用execute並且SynchronousQueue.offer失敗,那麼您將不得不創建一個特殊的工作線程,該線程捕獲其他線程之一併在執行之前標記它們停止,並在執行之後再次標記它們以恢復。