2017-02-16 121 views
0

編輯:我的問題是不同的,它與鏈接的問題沒有關係。Java等待所有主題完成

我跟隨完成處理程序的代碼。

FutureTask<Void> futureTask = new FutureTask<Void>(() -> { 
    System.out.println("callback"); 
    return null; 
}); 

Runnable task =() -> { 
    for(int i=0; i<5; i++) { 
     System.out.println(Thread.currentThread().getName() + " " + i); 
    } 
    futureTask.run(); 
}; 

new Thread(task).start(); 
new Thread(task).start(); 

基本上我正在尋找可變數量的任務的完成處理程序,或者是否有另一種方法?

我從answer中受到啓發,但似乎它是某個庫的一部分,而我正在尋找本地解決方案。

Completable Future ???

這是我最終以結果處理程序完成未來的嘗試。

public void test() { 
    CompletableFuture 
      .supplyAsync(() -> method1()) 
      .supplyAsync(() -> method2()) 
      .supplyAsync(() -> result()); 
} 

public String method1() { 
    System.out.println("calling 1"); 
    return "method1"; 
} 

public String method2() { 
    System.out.println("calling 2"); 
    return "method2"; 
} 

public String result() { 
    System.out.println("result"); 
    return "result"; 
} 
+0

爲什麼'futureTask.run();'不能用舊方法替換? –

+0

你基本上可以通過執行一個在其前任調用Thread.join()來鏈接你的任務,然後做你想做的任何事情。 – Izruo

+0

可能重複的[等到所有線程完成他們的工作在java](http://stackoverflow.com/questions/7939257/wait-until-all-threads-finish-their-work-in-java) –

回答

0

保存的鏈接,你所創建的線程,並調用join()

Thread a = new Thread(task); 
Thread b = new Thread(task); 
a.start(); 
b.start(); 

a.join(); 
b.join(); 
//guaranteed that both threads have completed here 
+0

它會在那裏阻止,我想調用這些線程並忘記它,方法返回,並且我期望在回調中進行跟進。感謝教會我'加入'儘管 – user2727195

+0

@ user2727195更好然後使用另一個線程然後運行連接和後續回調 – ControlAltDel

+0

好的,你有一個點。爲了在這裏擴展知識,你知道CompletableFuture,它適用於我的問題嗎? – user2727195

0

根據你想要多少控制,你可以使用的ThreadPoolExecutor:

tpe.execute(Runnable接口);

等待活動計數== 0;

然後關閉執行程序。

或將線程保留在結構中。

等待一個特定的TTL然後打斷他們,如果狀態是RUNNABLE

+0

的權利。這似乎是isTerminated()可能是等待這個方法。我將這個添加到我的答案中,但認爲它會使事情過於複雜 – ControlAltDel

+0

這隻取決於人們想要如何處理它們。我傾向於避免使用游泳池,因爲當我想要時,我寧願保留拉拔插頭的能力 – efekctive

+0

如果您有'ThreadPoolExecutor',只需使用'invokeAll'提交任務列表並等待它們完成。不需要使用諸如活動計數或關閉之類的kludges。 – Holger

1

一個簡單的方法是提交您的Runnable(縣)一個ExecutorService,然後調用shutdown,然後調用awaitTermination

ExecutorService executor = Executors.newWorkStealingPool(); 
executor.submit(task); 
executor.submit(task); 

executor.shutdown(); 
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 

無需使用CompletableFuture。

+0

你能讓它成爲一個不同的調用者和不同的響應者,執行者將是一種不同的方法和回調,結果將在一個不同的方法。 – user2727195

2

假設你的方法result()返回要檢索的值,即聲明如下Type result(),你可以使用

CompletableFuture<Type> f = CompletableFuture.allOf(
    CompletableFuture.runAsync(() -> method1()), 
    CompletableFuture.runAsync(() -> method2()) 
).thenApply(_void -> result()); 

每個runAsync創建一個單獨的異步CompletableFuture將一次Runnable完成已執行。它與supplyAsync相同,只是它不返回結果。

allOf創建一個CompletableFuture,一旦完成所有指定的期貨,即可完成,因此,任何鏈接的相關操作只會在所有期貨完成後才執行。通過使用thenApply,我們創建一個依賴於未來的將來將完成的返回值爲result()

如果result()不打算返回一個值,而只是所有其他的動作完成之後應該執行的操作,您可以使用

CompletableFuture.allOf(
    CompletableFuture.runAsync(() -> method1()), 
    CompletableFuture.runAsync(() -> method2()) 
).thenRun(() -> result()); 

代替。