A barrier makes a group of threads meet at a barrier point.
A thread from a group arriving at the barrier waits until all threads in that group arrive.
You can divide a task into subtasks which can be performed in a separate thread.
After they all finished we can combine their results.
The action of combination is called barrier action.
CyclicBarrier class from java.util.concurrent package is an implementation of the barrier synchronizer.
Threads from cyclic barrier can reused by calling its reset() method.
A barrier action which is a Runnable task can be set to the CyclicBarrier and executed before all threads are released.
await() method of the CyclicBarrier class returns the arrival index of the thread calling it.
The last thread to arrive at the barrier has an index of zero.
The first arrived has an index of the number of threads in the group minus one.
The following code shows how to use a cyclic barrier.
import java.util.Random; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class Main { public static void main(String[] args) { // Create a barrier for a group of three threads with a barrier action Runnable barrierAction = () -> System.out.println("do the combination..."); CyclicBarrier barrier = new CyclicBarrier(3, barrierAction); for (int i = 1; i <= 5; i++) { MeetAtBarrier t = new MeetAtBarrier(i, barrier); t.start();/* ww w . j a v a 2 s.co m*/ } } } class MeetAtBarrier extends Thread { private CyclicBarrier barrier; private int ID; public MeetAtBarrier(int ID, CyclicBarrier barrier) { this.ID = ID; this.barrier = barrier; } public void run() { try { int workTime = 3; System.out.println("Thread #" + ID + " is going to work for " + workTime + " seconds"); Thread.sleep(workTime * 1000); System.out.println("Thread #" + ID + " is waiting at the barrier..."); this.barrier.await(); System.out.println("Thread #" + ID + " passed the barrier..."); } catch (Exception e) { System.out.println("Barrier is broken..."); } } }