我正在使用具有不同運行時間的任務的多線程應用程序。當一個線程完成時,是否有辦法從一個仍在運行的線程中接管一些任務?Java:如何將完成的線程從正在運行的線程提取任務
這裏是一個例子。我用5個線程啓動了我的程序,每個程序都有50個任務。當最快的運行線程完成時,另一個線程仍然有40個任務要完成。我怎樣才能讓完成的線程從另一個線程執行20個任務,因此每個線程都繼續工作20個,而不是等待正在運行的線程完成剩下的40個任務?
我正在使用具有不同運行時間的任務的多線程應用程序。當一個線程完成時,是否有辦法從一個仍在運行的線程中接管一些任務?Java:如何將完成的線程從正在運行的線程提取任務
這裏是一個例子。我用5個線程啓動了我的程序,每個程序都有50個任務。當最快的運行線程完成時,另一個線程仍然有40個任務要完成。我怎樣才能讓完成的線程從另一個線程執行20個任務,因此每個線程都繼續工作20個,而不是等待正在運行的線程完成剩下的40個任務?
一個ForkJoinPool與其他類型的ExecutorService的不同之處主要憑藉用人偷盜的:所有的線程池中試圖找到並執行其他活動任務創建子任務(最終阻塞等待如果沒有任何工作)。當大多數任務產生其他子任務時(如大多數ForkJoinTasks),這可以實現高效處理。在構造函數中將asyncMode設置爲true時,ForkJoinPools可能也適合用於永不連接的事件樣式任務。
的Java 8提供了執行人
static ExecutorService newWorkStealingPool()
多了一個API創建使用所有可用的處理器作爲其目標並行水平工作竊取線程池。
看一看這個igvtia article通過Ilya Grigorik
更多的細節。
看一看其它相關的Java併發API @tutorials像ThreadPoolExecutor
,ExecutorService
等
謝謝拉文德拉。每個人的輸入都有幫助,但ForkJoinPool似乎是我正在尋找的東西(我們已經在使用線程池)。在你鏈接的文章中解釋的想法是我想到的,所以我會給ForkJoinPool一個嘗試。 –
如果您需要偷工減料的行爲,但對真正的fork/join遞歸任務分解不感興趣,請考慮使用['Executors.newWorkStealingPool'](http://docs.oracle.com/javase/8/docs/api改爲/java/util/concurrent/Executors.html#newWorkStealingPool--)。雖然這個方法目前確實返回了一個'ForkJoinPool'實例,它將來可能會返回一個更高效的工作線程池實現。 – glts
最好使用ThreadPoolExecutor
。它會自動將任務分配給空閒線程。
使用線程池,其中創建感謝Executors類:
ExecutorService es = Executors.newFixedThreadPool(5);
List<Runnable> tasks = // create your 50 runnable
List<Future<?>> futures = new ArrayList<>(tasks.size());
for(Runnable r : tasks) {
Future<?> f = es.submit(t);
futures.add(f);
}
的文檔解釋了相當不錯它是如何工作的,所以我建議你給它看看。
不要讓線程承擔多個任務。這樣,任何完成其任務的線程都會採用隊列中的下一個可用任務。這些線程並不是爲每個任務創建的,而是正在被重用,所以幾乎沒有開銷。
考慮 - 2個線程每個都有20個任務,並且如果第二個線程尚未完成,您希望第二個線程從第一個線程接管任務。將此比較爲由2個線程服務的隊列中的40個任務,這意味着任務總是儘可能快地執行,而不需要在線程間移動它們的複雜性。
我沒有看到問題中的邏輯 - 如果由於排序問題而導致無法進行多線程的任務組(這是我看到提交本身是一組任務的唯一原因任務放到隊列中),那麼你不能讓另一個線程接管未完成的處理(因爲那麼整個組的排序將被破壞)。如果您不需要排序處理,那麼將所有任務放到隊列中並儘快執行。
如果您總是希望來自給定組的任務能夠更快執行,請爲其分配更高的優先級並使用由多個線程提供服務的優先級隊列。
查看[Executor](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html) – jhamon
您正在描述「盜取工作」。 [用於'ForkJoinPool'的Javadoc](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ForkJoinPool.html)明確指出它「與其他類型的ExecutorService主要不同僱用工作偷竊的美德「。 –
@AndyTurner不是真的,他只是想把任務分配給一個可用的線程 –