CountDownLatch: Coordinating Thread Execution in Java
When developing concurrent applications, there are often scenarios where you need to ensure multiple threads complete their tasks before proceeding to the next phase. Java's CountDownLatch utility provides an elegant solution for such synchronization requirements.
Consider a team collaboration scenario where team members must complete their individual tasks before the team can move forward with the next phase of the project. Each team member has different task complexities, resulting in varying completion times.
Team Collaboration Example
package com.example.concurrency;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
public class TeamProject {
public static void main(String[] args) throws InterruptedException {
int teamSize = 5;
int taskComplexity = 0;
Random random = new Random();
// Latch to signal when the project starts
CountDownLatch startLatch = new CountDownLatch(1);
// Latch to wait for all team members to complete their tasks
CountDownLatch completionLatch = new CountDownLatch(teamSize);
// Create and start team member threads
for(int i = 1; i <= teamSize; i++) {
taskComplexity = random.nextInt(teamSize);
new Thread(new TeamMember("member" + i, taskComplexity, startLatch, completionLatch)).start();
}
// Signal that the project has started
System.out.println("*** Project Phase Begins ***");
startLatch.countDown();
// Wait for all team members to complete their tasks
completionLatch.await();
// Proceed to next phase
System.out.println("All tasks completed. Moving to next phase...");
System.out.println("*** Project Phase Ends ***");
}
}
Team Member Implementation
package com.example.concurrency;
import java.util.concurrent.CountDownLatch;
public class TeamMember implements Runnable {
private final String memberName;
private final int taskDuration;
private final CountDownLatch startLatch;
private final CountDownLatch completionLatch;
public TeamMember(String name, int duration, CountDownLatch startLatch, CountDownLatch completionLatch) {
this.memberName = name;
this.taskDuration = duration;
this.startLatch = startLatch;
this completionLatch = completionLatch;
}
@Override
public void run() {
try {
// Wait for the project to start
startLatch.await();
// Perform the assigned task
Thread.sleep(taskDuration * 1000);
// Notify that the task is completed
System.out.println(memberName + ": Task completed, waiting for other members.");
completionLatch.countDown();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println(memberName + ": Task was interrupted.");
}
}
}
The CountDownLatch class is part of java.util.concurrent and provides a flexible mechanism for allowing one or more threads to wait for a set of operations to complete. The constructor takes an integer count that represents the number of times the countDown() method must be called before threads waiting on the latch can proceed.
In this example, we use two latches:
- The startLatch ensures all team members are ready before any of them begins their task.
- The completionLatch ensures the main thread waits until all team members have completed their tasks before proceeding to the next phase.
This pattern is particularly useful in scenarios where you need to coordinate the execution of multiple threads, ensuring that certain prerequisites are met before continuing with the program flow.