Cyclic Barrier in Java
Programmers often find it challenging to run multiple threads simultaneously. Java introduces the idea of concurrency, which enables us to run many threads concurrently, making this work simpler. Concurrent programming has the benefit of not interfering with other threads if one Thread fails to complete its task. The cyclic barrier is a concept used in concurrent programming to synchronize threads. This section will cover cyclic barriers and the Java Cyclic Barrier class.
What is the Cyclic barrier in Java?
A group of threads can wait for one another until they arrive at a common barrier position using the concurrent utility technique of synchronization known as the cyclic barrier. It is helpful in Java projects when a set number of threads must wait for one another and are of a fixed size. The word "cyclic" is employed because of its repeated meaning. Once all queued threads are freed, the barrier may be utilized again. The barrier that ensures every Thread has finished running before arriving at this point is the point. The cyclic barrier is the name given to the mechanism as a result. Cyclic barriers, in essence, maintain a thread count. The barrier opens up for the waiting threads once the number of threads that invoked await() equals the number of threads. Additionally, an action carried out once all threads have already reached the barrier can be used to start the CyclicBarrier. The results of each Thread's computation while it is waiting within the barrier can be combined or used in this action.
So, because the latch cannot be used again once the count hits zero, we can substitute CyclicBarrier for CountDownLatch but not vice versa.
Advantages of Cyclic Barrier
- It is resettable and repeatable.
- Whenever the barrier is reached, we should break it.
- It offers a post-barrier routine.
- Additionally, it offers a form of the split merge.
When to use the Cyclic Barrier?
Imagine that an application wants to read five documents utilizing five different threads. After receiving and parsing all five files, the application must call an additional thread for additional processing. Parse the read lines. When all threads have reached the barrier, we may utilize Cyclic Barrier, which offers a runnable action, to execute the Thread.
- It can be used to divide a big task into smaller sub-tasks, each of which is handled by a different thread. When all threads have completed the identical task, the barrier's final task combines the results of all the threads.
- Additionally, it is utilized in multiplayer games to determine when the action begins.
How to use Cyclic Barrier?
We must first create an instance of a CyclicBarrier class using one of the two operators before we can use the cyclic barrier. Parse the necessary amount of threads which will wait for one another in the function Object () { [native code] }. Use the await () method when all the specified threads have reached a common point.
Relating to the CyclicBarrier object. The threads are put on hold until all threads call the await () function for the same CyclicBarrier object. When all threads call the await () function, the barrier is broken, and all threads carry on with their operations after the barrier has been broken.
When a non-null barrier function was specified in the function Object () { [native code] } and the current Thread was the last to arrive, the current Thread executes the operation before letting some other threads proceed.
Java cyclic barrier class
CyclicBarrier is a class in the Java language that is a part of the java.util.concurrent package. In addition to Java classes such as CountDownLatch, ConcurrentHashMap, CopyOnWriteArrayList, and BlockingQueue, it was first introduced in Java 5. We can keep track of the thread count, thanks to the class.
Methods Important for the Cyclic Barrier Class
The following methods are included in the Cyclic Barrier class:
Methods | Description |
await() | This method will return Thread's current arrival index. |
await(long time, TimeUnit units) | This method will Wait until the specified waiting period has passed or until all parties (threads) have called await on this barrier. |
getNumberWaiting() | This method is employed to obtain the number of parties stuck in the await () method and currently waiting at the barrier. The technique is frequently used for tests and debugging. |
getParties() | This method produces a numerical value that indicates how many parties are necessary to overcome this barrier. |
isBroken() | If one or more parties left this barrier owing to an interruption, timeout, or reset since construction, or if a barrier operation failed because of an exception, the procedure returns a boolean value. Returns false if not. |
reset() | This method restores the barrier towards its initial condition. If any parties are presently awaiting at the barrier, the procedure raises a BrokenBarrierException. |
Example of Cyclic Barrier
CyclicBarrier1 .java
// importing all the required packages
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.BrokenBarrierException;
public class CyclicBarrier1
{
public static void main(String args[])
{
// Object creation for the Cyclic Barrier Class
CyclicBarrier obj = new CyclicBarrier(3, new Sucess());
//initializing three threads to read three different files
Thread thrd1 = new Thread(new Reader("1st thread", "1st file", obj));
Thread thrd2 = new Thread(new Reader("2nd thread", "2nd file", obj));
Thread thrd3 = new Thread(new Reader("3rd thread", "3rd file", obj));
//Thread is invoked here by calling the start method
thrd1.start();
thrd2.start();
thrd3.start();
System.out.println("Successful !");
}
}
class Reader implements Runnable
{
private String name;
private String fname;
private CyclicBarrier obj;
Reader(String name, String fname, CyclicBarrier CB)
{
this.name = name;
this.fname = fname;
this.obj = obj;
}
@Override
public void run()
{
System.out.println("Currently reading the file " + fname + " Current thread " + name);
try
{
// Suspending the current Thread using await() method
obj.await();
}
catch (InterruptedException ae)
{
System.out.println(ae);
}
catch (BrokenBarrierException ae)
{
System.out.println(ae);
}
}
}
class Success implements Runnable
{
@Override
public void run()
{
System.out.println("Success class, will start after processing as all files are done that is read.");
}
}
Output:
Successful !
Currently reading the file 1st file Current Thread 1st Thread
Currently reading the file 3rd file Current thread 3rd thread
Currently reading the file 2nd file Current Thread 2nd Thread
Success class will start after processing as all files are done that is read.
Reusing CyclicBarrier
As was said before, when all the waiting threads are freed, CyclicBarrier can be reused. Let's use a Java application to analyze CyclicBarrier's reusability.
As mentioned above, three threads were used in the application to retrieve three files. We would add three additional threads to the program in the next section to read three additional files.
CyclicBarrier2.java
// importing all the required packages
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.BrokenBarrierException;
public class CyclicBarrier2
{
public static void main(String args[])
{
// Object creation for the Cyclic Barrier Class
CyclicBarrier obj = new CyclicBarrier(3, new Success());
//Initializing three threads to read three different files
Thread thrd1 = new Thread(new Reader("1st thread", "1st file", obj));
Thread thrd2 = new Thread(new Reader("2nd thread", "2nd file", obj));
Thread thrd3 = new Thread(new Reader("3rd thread", "3rd file", obj));
//Thread is invoked here by calling the start method
thrd1.start();
thrd2.start();
thrd3.start();
System.out.println("New set of threads starting there execution");
Thread thrd4 = new Thread(new Reader("4th thread", "4th file", obj));
Thread thrd5 = new Thread(new Reader("5th thread", "5th file", obj));
Thread thrd6 = new Thread(new Reader("6th thread", "6th file", obj));
//Thread is invoked here by calling the start method
thrd4.start();
thrd5.start();
thrd6.start();
}
}
class Reader implements Runnable
{
private String name;
private String fname;
private CyclicBarrier obj;
// Object creation of the Reader class
Reader(String name, String fname, CyclicBarrier obj)
{
this.name = name;
this.fname = fname;
this.obj = obj;
}
@Override
public void run()
{
System.out.println("Currently reading the file " + fname + " Current thread " + name);
try
{
// Suspending the current Thread using await() method
CB.await();
}
catch (InterruptedException ae)
{
System.out.println(ae);
}
catch (BrokenBarrierException ae)
{
System.out.println(ae);
}
}
}
class Success implements Runnable
{
@Override
public void run()
{
System.out.println("Success class, will start after processing as all files are done that is read.");
}
}
Output:
New set of threads starting there execution
Currently reading the file 5th file Current thread 5th thread
Currently reading the file 3rd file Current thread 3rd thread
Currently reading the file 2nd file Current Thread 2nd Thread
Success class will start after processing as all files are done that is read.
Currently reading the file 1st file Current Thread 1st Thread
Currently reading the file 6th file Current Thread 6th Thread
Currently reading the file 4th file Current Thread 4th Thread
Success class will start after processing as all files are done that is read.