Tag Archives: threads

How to use CountDownLatch

Sometimes we need to synchronize the results of several threads running simultaneously, we need to run some task once some others have finished. We can use CountDownLatch class to do this.

The Pizza Example

Let’s use another silly example. I want to have pizza for dinner, so I’m going to cook it. While the oven is preheating (it takes 5 min) I can prepare the pizza itself (it takes 2 min). Once everything is ready I can put the pizza inside the oven. That’s easy: as the oven takes longer to get preheated than me to get the pizza ready, I can put the pizza inside as soon as the oven is ready. There’s no need to synchronize threads…

But sometimes I turn on the radio and the music distracts me. In this case it takes me to prepare the pizza from 4 to 7 minutes. We don’t know which process will finish first, we have to wait until both processes have finished to put the pizza in the oven.

final CountDownLatch latch = new CountDownLatch(2);

Thread preheat = new Thread() {

	@Override
	public void run() {
		// The oven takes 5 minutes to get ready
		// (we use 5 seconds instead)
		try {
			Thread.sleep(5000);
			System.out.println("The oven is ready.");
		} catch (InterruptedException e) {
		} finally {
			latch.countDown();
		}
	}
	
};

Thread preparePizza = new Thread() {

	@Override
	public void run() {
		// It takes me from 4 to 7 minutes to prepare the pizza
		Random random = new Random();
		int time = random.nextInt(3000);
		try {
			Thread.sleep(4000+time);
			System.out.println("The pizza is ready.");
		} catch (InterruptedException e) {
		} finally {
			latch.countDown();
		}
	}
	
};

preheat.start();
preparePizza.start();

try {
	latch.await();
	System.out.println("The pizza is in the oven.");
} catch (InterruptedException e) {
}

First of all we’re starting a CountDownLatch instance. We pass the number 2 as an argument to the constructor to tell it that there will be two processes to wait for.

Next we create a thread for the oven, the sleep simulates the preheating process. We’re using seconds instead of minutes so the program won’t be idle for such a long time.

Next we create the preparing pizza thread. With a random number we simulate the distracting song from the radio. At the end of both processes there is a line, latch.countDown(), that tells the CountDownLatch that the process has finished. You may have noticed that latch.countDown() is in the finally block. We want it to be executed no matter what exception is thrown. If the program never reaches this line it’ll hang!

Next we start both threads and tell the latch to wait for them. This is accomplished with the latch.await() line. It’ll suspend the main thread until both processes have finished (when latch.countDown() is reached).

After running this program we get something like this:

The oven is ready.
The pizza is ready.
The pizza is in the oven.

But we could also get:

The pizza is ready.
The oven is ready.
The pizza is in the oven.

Regardless of how long it takes me to prepare the pizza, “The pizza is in the oven.” won’t be shown until both tasks have finished.

How to use CyclicBarrier

Sometimes we need to run several threads at once, make them start at the same time. The Java API provides us a class, CyclicBarrier, to accomplish this.

The Race Example

Let’s assume you have to create a silly program that simulates a car race. The semaphore (our CyclicBarrier) waits for all drivers to be ready to go green, then every driver drives until they get to the finish line.

First of all, the Driver class. It will have two variables: the driver’s name and his best lap time.

class Driver {
	
    private String name;
    private Double bestTime;

    public Driver(String name, Double bestTime) {
        this.name = name;
        this.bestTime = bestTime;
    }

    //getters & setters...
}

Next we’ll create a drive method. It represents the driver driving and it will last the time the driver takes to complete a lap. Finally, if the lap time is better than his best time, the bestTime variable is updated.

public void drive() throws InterruptedException {
    System.out.println(name + " starts running!!");
    Double lapTime = getLapTime();
    Thread.sleep(Math.round(lapTime*1000));
    System.out.println(name + " finished in " + lapTime + " seconds.");
    if (lapTime < bestTime) {
        System.out.println(name + " has beaten his best time!!");
        bestTime = lapTime;
    }
}

As you can see, we need to implement the getLapTime() method. As drivers aren’t machines, they don’t perform the same time every lap, so it will return a random number around their best time. The gap is 1 second, they can beat their best time up to 1 second or take a worse time up to 1 second too.

    private Double getLapTime() {
        Random r = new Random();
        return bestTime + r.nextDouble()*2 - 1;
    }

Driver class is ready. Now we want to use each driver in a different thread so they race at the same time. We’ll create three drivers, use them on three threads, and we’ll use CyclicBarrier to make them wait until every driver is ready.

In this example, their best performance are around 13 seconds (it’s a short circuit). Every driver arrives to the grid 2.5 seconds later than the last one, so the semaphore won’t go green until the last driver arrives, 5 seconds later than the first one.

String[] names =  {"Ayrton", "Michael", "Niki"};
Double[] bestTimes = {13.21, 13.03, 13.25};

final CyclicBarrier semaphore = new CyclicBarrier(3);

for (int i=0; i<3; i++) {
    final Driver driver = new Driver(names[i], bestTimes[i]);
    Thread t = new Thread() {
        public void run() {
            System.out.println(driver.getName() + " is ready.");
            try {
                semaphore.await();
                driver.drive();
            } catch (InterruptedException | BrokenBarrierException e) {
            }
        }
    };
    t.start();
    Thread.sleep(2500);
}

When we create the CyclicBarrier, our semaphore, we pass to the constructor the number of threads it’ll wait until it starts them all. Then we create a thread that will be suspended. The key is the semaphore.wait(), every following line of code won’t be executed until the CyclicBarrier starts the thread.

To get in the pool of the CyclicBarrier, we have to start the thread as usually. Finally we make the main thread sleep for 2.5 seconds before creating the next driver.

After running this program we’ll get something like this:

Ayrton is ready.
Michael is ready.
Niki is ready.
Ayrton starts running!!
Michael starts running!!
Niki starts running!!
Niki finished in 12.790270035868033 seconds.
Niki has beaten his best time!!
Ayrton finished in 13.484038866959247 seconds.
Michael finished in 13.909761762654298 seconds.

The first three lines will take 5 seconds to get printed, with a 2.5 seconds gap between them. But as soon as Niki is ready, we’ll get the following 3 lines, the racing start. This happens even though the main thread is suspended for another 2.5 seconds. They’re running on their own threads.

Despite of being the last one to arrive to the grid before the race, Niki wins the race after 12.79 seconds!

You can get the complete sourcecode on my GitHub project.