Imagine a scenario where you have N threads and can only do something when M of them are ready. Java already has this built in since 1.5 with the CyclicBarrier.
From the Javadoc we see the CyclicBarrier is A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.
Let’s take an example:
We have a bar that will only open if 4 drinkers are waiting
Once the 4th person that is waiting at the bar arrives we open the bar
We want to print a message when the bar opens
Pay close attention to the 5th and 6th drinker
Let us jump right into the example. Here we will create a Bar that serves alcohol, we’ll create 6 drinkers with names and a drink of their choice and have them wait at the bar. If they wait too long they will go to other bars. Let’s use the CyclicBarrier to see how this works.
The implementation is as follows:
Drinkers are Callables that return a Drinker Status.
The Bar itself is an ExecutorService and Drinker Callables are submitted to it returning Futures.
In the call function of each Drinker we will await the CyclicBarrier to be tripped.
Here we go. Let’s create some Callable’s that will wait at a bar for their drink of choice. Only open the Bar doors for drinks where there are 4 drinkers.
The output of this example is as follows:
Jane is waiting at the bar door for a Everclear with 0 others
John is waiting at the bar door for a Pabst Blue Ribbon with 0 others
Anup is waiting at the bar door for a Blue Moon with 0 others
Vish is waiting at the bar door for a Fireball with 0 others
Mark is waiting at the bar door for a Laphroaig with 0 others
Lisa is waiting at the bar door for a Wild Turkey with 0 others
Yay!! The bar is open.
Lisa can order a Wild Turkey
John can order a Pabst Blue Ribbon
Vish can order a Fireball
Mark can order a Laphroaig
Anup waited too long and is going elsewhere for a drink. Others that are waiting are leaving
Jane abnormally left the party because of interruption, failure, or timeout. Barrier is broken.
Jane is walking away from the bar
John is drinking
Anup is walking away from the bar
Vish is drinking
Lisa is drinking
Mark is drinking
We closed the bar with drinkers waiting
Now let’s examine it since there is more than meets the eye here.
We never got a good count of how many people were waiting on the cyclic barrier since all Callables were called at once
The 4 Drinkers John, Vish, Lisa and Mark got past the cyclic barrier and started drinking
Anup waited to long and left the bar since there were only 6 people and we need multiples of 4 to trip the barrier
After Anup left the Bar and went elsewhere, Jane left too.
Jane and Anup didn’t get into the Bar
So there are some details of the CyclicBarrier that may or may not be good for your application. Firstly, the barrier trips after N parties reach it. This N is set in the constructor. However, after the barrier is tripped we need to look further for ways to reset the barrier, create a new barrier in a thread safe manner or explore other means. This example works great for the 4 drinkers required to trip the barrier. But as you can see the complexity and ways to handle the 5th and 6th drinker become a bit unruly.