2017-02-16 120 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()); 

代替。