I am trying to map some business case to usage of Cyclic Barriers. Let's say we have a promotional offer going on and only 3 customers can get the promotional offer. The rest will not get the offer.
To map this scenario, I have made use of Cyclic Barrier. Even though the code is working, I am not sure how to handle the scenario, where some of the customers, will not be able to get the offer. Right now, I tried to use await() API with a timeout value, so that I can catch TimeoutException and let the customer know, that he could not avail the promotional offer. This led to BarrierBrokenException for another waiting thread.
I would like to know, how can we gracefully handle these scenarios such that the selected customers avail promotional offer, while those who could not follow a different code path.
My code -
public class CyclicBarrierExample {
public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
Thread[] threads = new Thread[5];
CyclicBarrier barrier = new CyclicBarrier(3, ()->{System.out.println("Barrier limit of 3 reached. 3 threads will get the promotional offer!");});
Runnable nr = new PromotionRunnable(barrier);
int i = 0;
for (Thread t : threads) {
t = new Thread(nr, "Thread " + ++i);
t.start();
}
System.out.println("main thread has completed");
}
private static class PromotionRunnable implements Runnable {
private final CyclicBarrier barrier;
public PromotionRunnable(final CyclicBarrier barrier) {
this.barrier = barrier;
}
/*
* As per the doc, BrokenBarrierException is thrown when another thread timed out while the current thread was waiting.
* This explains why we are able to see both Timeout and Broken Barrier Exceptions.
*/
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " trying to get the promotional offer!");
try {
barrier.await(2000L, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
return;
} catch (BrokenBarrierException e) {
System.out.println(Thread.currentThread().getName() + " could not get the promotional offer, due to barrier exception");
return;
} catch (TimeoutException e) {
System.out.println(Thread.currentThread().getName() + " could not get the promotional offer, due to timeout exception");
return;
}
System.out.println(Thread.currentThread().getName() + " got the promotional offer!");
}
}
}
Output from one of the runs -
- Thread 1 trying to get the promotional offer!
- Thread 4 trying to get the promotional offer!
- main thread has completed
- Thread 3 trying to get the promotional offer!
- Thread 2 trying to get the promotional offer!
- Thread 5 trying to get the promotional offer!
- Barrier reached for top 3, they will get the promotional offer!
- Thread 2 got the promotional offer!
- Thread 1 got the promotional offer!
- Thread 5 got the promotional offer!
- Thread 3 could not get the promotional offer, due to timeout exception
- Thread 4 could not get the promotional offer, due to barrier exception