我的要求是在启动依赖作业之前等待两个线程完成执行。
为了做到这一点,我可以创建一个 CountDownLatch
和一个 Waiter
Thread
来等待 CountDownLatch
变为零。一个限制是我不能使用主线程来等待两个线程完成。主线程继续执行其他任务。
这东西确实有用。但是,与可靠的设计相比,我对此有一种解决方法。
我的问题如下:
- 当前方法有哪些明显缺陷?例如杂散信号
- 您会推荐哪种设计?
我当前的代码:
class Waiter implements Runnable {
private CountDownLatch latch;
Waiter (CountDownLatch latch){
this.latch = latch;
}
@Override
public void run() {
System.out.println("Waiter Started running..." + latch.getCount());
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Waiter ready to trigger Next Job!");
}
}
class Processor implements Runnable {
private CountDownLatch latch;
Processor (CountDownLatch latch){
this.latch = latch;
}
@Override
public void run() {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
}
}
public class CountDownLatchDemo {
public static void main (String[] args) throws InterruptedException{
CountDownLatch latch = new CountDownLatch(2);
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i=0; i< 2; i++){
executor.submit(new Processor(latch));
}
ExecutorService waitExecutor = Executors.newFixedThreadPool(2);
waitExecutor.submit(new Waiter(latch));
Thread.sleep(3000);
executor.shutdown();
waitExecutor.shutdown();
System.out.println("Keep doing other things! Sleep here is just for help you run this code for test!");
}
}
最佳答案
CountDownLatch
是适合您任务的解决方案。但 Java 8 提供了另一种选择——CompletableFuture
。您可以为您的任务创建两个这样的 futures,然后使用其中一种方法等待 futures 完成并异步执行其他操作。例如:
// Submit Task 1
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println("Task 1 completed");
return 5;
});
// Submit Task 2
CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
System.out.println("Task 2 completed");
return 7;
});
// This call will create a future that will wait for f1 and f2 to complete
// and then execute the runnable
CompletableFuture.allOf(f1, f2).thenRun(() -> {
System.out.println("Both completed");
});
所有这些调用都将异步处理,您的主线程将继续运行。如果您在第三个任务中需要前两个任务的结果,您可以使用 thenAcceptBothAsync()
而不是 allOf()
:
f1.thenAcceptBothAsync(f2, (a, b) -> System.out.println("Result = " + (a + b)));
CompletableFuture
中有很多方法可以让您创建异步执行任务链。 JVM 使用默认的 ForkJoinPool
来执行它们,但您可以提供自己的 Executor
来完成您的 future 并用它们做很多其他有用的事情。
关于java - 有没有比使用 CountDownLatch 更好的等待两个线程完成任务的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39546565/