Reputation: 2208
My requirement is to wait for two threads to complete execution before kickstarting a dependent job.
In order to do this, I am able to create a CountDownLatch
and a Waiter
Thread
which will wait for the CountDownLatch
to become zero. One constraint is I cannot use the main thread to wait for the two threads to complete. The main thread continues with other tasks.
This thing does work. However, I get a feel of workaround in this than a solid design.
My questions are the following:
My current code:
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!");
}
}
Upvotes: 4
Views: 3431
Reputation: 6197
CountDownLatch
is a proper solution for your task. But Java 8 provides another option – CompletableFuture
. You can create two such futures for your tasks and then use one of the methods that wait for futures completion and execute something else asynchronously. For instance:
// 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");
});
All these calls will be processed asynchronously and your main thread will continue running. If you need the results of the first two tasks in your third task, you can use thenAcceptBothAsync()
instead of allOf()
:
f1.thenAcceptBothAsync(f2, (a, b) -> System.out.println("Result = " + (a + b)));
There're lots of methods in CompletableFuture
that allow you to create chains of asynchronously executed tasks. JVM uses the default ForkJoinPool
to execute them, but you can provide your own Executor
s to complete your futures and do a lot of other useful things with them.
Upvotes: 6