Welcome to our Java CountDownLatch tutorial! In this lesson, we'll delve into the fascinating world of synchronization, exploring the CountDownLatch utility class in Java. This powerful tool allows one or multiple threads to wait for a set of operations to complete before continuing execution. It's particularly useful in scenarios where multiple tasks need to be executed in a specific sequence or depend on each other. Let's get started!
In simple terms, a CountDownLatch is a synchronization tool that enables one or multiple threads to wait for a particular condition to become true. Once that condition is met, the waiting threads can proceed with their execution.
To create a CountDownLatch, you'll need to instantiate the CountDownLatch class with the desired number of counts. The number of counts represents the number of times the countDown() method must be called before the waiting threads can continue.
CountDownLatch countDownLatch = new CountDownLatch(3);In the example above, we've created a CountDownLatch with an initial count of 3.
Now that we have our CountDownLatch, let's see how to use it in a multi-threaded environment. We'll create three worker threads and a main thread. The main thread will use the await() method to wait for the worker threads to complete their tasks.
// Main thread
countDownLatch.await();
// Worker thread
countDownLatch.countDown();In the example above, the main thread calls await() to wait for the worker threads to complete. Each worker thread calls countDown() when their task is done, decrementing the count of the CountDownLatch.
Let's dive deeper by exploring real-world scenarios that require the use of CountDownLatch.
In this example, we'll create a downloader application that can download multiple files concurrently but with a limit on the number of simultaneous downloads.
// CodeYourCraft DownloadManager
// Count of simultaneous downloads
int simultaneousDownloads = 3;
CountDownLatch countDownLatch = new CountDownLatch(files.length);
// Create a list of DownloadTask objects
List<DownloadTask> tasks = new ArrayList<>();
for (File file : files) {
DownloadTask task = new DownloadTask(file, countDownLatch);
tasks.add(task);
// Start the DownloadTask
task.start();
}
// Wait for all DownloadTasks to complete
countDownLatch.await();In this example, we have a DownloadManager class that manages a list of DownloadTask objects. Each DownloadTask downloads a single file concurrently, but only simultaneousDownloads tasks can run at a time, thanks to the CountDownLatch.
The producer-consumer problem is a classic example of multi-threading in computer science. Here, we'll use CountDownLatch to ensure the producer doesn't produce data faster than the consumer can consume it.
// CodeYourCraft Buffer
int bufferSize = 10;
BlockingQueue<Integer> buffer = new LinkedBlockingQueue<>(bufferSize);
CountDownLatch producerLatch = new CountDownLatch(producerCount);
CountDownLatch consumerLatch = new CountDownLatch(bufferSize);
// Producer thread
for (int i = 0; i < producerCount; i++) {
producer.put(buffer, i);
producerLatch.countDown();
}
// Consumer thread
for (int i = 0; i < bufferSize; i++) {
int value = buffer.take();
consumerLatch.countDown();
}
// Wait for producer to finish producing data
producerLatch.await();
// Wait for consumer to finish consuming data
consumerLatch.await();In this example, we have a Buffer that stores integers produced by a producer and consumed by a consumer. The CountDownLatch is used to synchronize the production and consumption of data, ensuring the buffer doesn't overflow or underflow.
In this tutorial, we explored the CountDownLatch class in Java, a powerful synchronization tool for waiting for specific conditions to become true. We learned how to create a CountDownLatch, use it in multi-threaded environments, and even delved into advanced examples like downloaders with limits and the producer-consumer problem.
By now, you should have a solid understanding of CountDownLatch and its applications. Happy coding! 💻🎉