Java looping Threads using CyclicBarrier

cyclicbarrier with executorservice
java cyclicbarrier vs countdownlatch
cycle barrier
phaser in java
cyclic barrier in java jenkov
countdownlatch example in java
exchanger in java
cyclicbarrier source code

I have a program with this general structure:

init
create CyclicBarrier
initialise all threads, attaching to barrier
*start all threads*
wait for join
display stats


*start all threads*
perform calculation
await barrier

My problem is I need the threads' run() method to keep looping until a certain condition is met, but pausing after every iteration to let all threads synchronise.

I've already tried attaching a Runnable method to the barrier, but this ends up requiring the recreation and restarting of each thread, which isn't a very good solution.

I've also tried using the CyclicBarrier's reset() method, but this just seems to cause errors on the existing threads, even when executed after all threads have completed.

My question is:

-Is it possible to 'reset' a barrier and have all the barrier's threads follow the same conditions as they did before the first invocations of await()?

-Or is there another method I should be using to achieve this?

Thanks in advance

Following @Totoro's answer, below is a little bit of example code which also incorporates the requirement "I need the threads' run() method to keep looping until a certain condition is met, pausing after every iteration to let all threads synchronise". That makes it complex pretty quick, but hopefully the program output will clarify the example code (or I should just make better examples).

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

public class BarrierCalc implements Runnable {

public static final int CALC_THREADS = 3;

private static final AtomicBoolean runCondition = new AtomicBoolean();
private static final AtomicBoolean stopRunning = new AtomicBoolean();

public static void main(String[] args) {

    CyclicBarrier barrier = new CyclicBarrier(CALC_THREADS + 1);
    for (int i = 0; i < CALC_THREADS; i++) {
         new Thread(new BarrierCalc(barrier)).start();
    }
    try {
        runCondition.set(true);
        barrier.await();
        showln(0, "STATS!");

        barrier.await();
        showln(0, "start looping 1");
        Thread.sleep(200);
        runCondition.set(false);
        showln(0, "stop looping 1");
        barrier.await();
        runCondition.set(true);

        barrier.await();
        showln(0, "start looping 2");
        Thread.sleep(100);
        runCondition.set(false);
        showln(0, "stop looping 2");
        barrier.await();

        stopRunning.set(true);
        showln(0, "finishing");
        barrier.await();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static final AtomicInteger calcId = new AtomicInteger();

private CyclicBarrier barrier;
private int id;

public BarrierCalc(CyclicBarrier barrier) {
    this.barrier = barrier;
    id = calcId.incrementAndGet();
}

public void run() {

    showln(id, "waiting for start");
    try {
        barrier.await(); // display stats
        barrier.await(); // start running
        int loopNumber = 0;
        while (!stopRunning.get()) {
            showln(id, "looping " + (++loopNumber));
            while (runCondition.get()) {
                Thread.sleep(10); // simulate looping
            }
            showln(id, "synchronizing " + loopNumber);
            barrier.await();
            showln(id, "synchronized " + loopNumber);
            // give main thread a chance to set stopCondition and runCondition
            barrier.await();
        }
        showln(id, "finished");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static final long START_TIME = System.currentTimeMillis();

public static void showln(int id, String msg) {
    System.out.println((System.currentTimeMillis() - START_TIME) + "\t ID " + id + ": " + msg);
}

}

Keep in mind that program output might not be in the order expected: threads that are writing at the same time to one synchronized output (System.out) are given write-access in random order.

Java.util.concurrent.CyclicBarrier in Java, In other words, a CyclicBarrier is used when multiple thread carry out different sub tasks and the output of these sub tasks need to be combined to form the final​  In this post, I will be discussing about CyclicBarrier; one of the thread synchronisation constructs provided as a part of java.util.concurrent package. CyclicBarrier is useful if a set of threads

The barrier.wait() will suspend the threads. The barrier is already in the main thread, it does not need another. In your algorithm above you show the threads being restarted after displaying stats. You should not need to do this. If the recently awakened threads are in a loop they will go back into the barrier.wait() again.

Concordinating threads with a CyclicBarrier: parallel sort (2), Example of using Java's CyclicBarrier to sort data in parallel. arbitrary number of iterations, the thread would sit in a loop, performing work then calling await(). Java.util.concurrent.CyclicBarrier in Java. CyclicBarrier is used to make threads wait for each other. It is used when different threads process a part of computation and when all threads have completed the execution, the result needs to be combined in the parent thread. In other words, a CyclicBarrier is used when multiple thread carry out different sub tasks and the output of these sub tasks need to be combined to form the final output.

You can take a look at my example where I played with CyclicBarrier.Here each worker makes some calculation and at the barrier the condition is checked. If it meets the condition than all workers stop calculations, otherwise they continue:

class Solver {
    private static final int REQUIRED_AMOUNT = 100;
    private static final int NUMBER_OF_THREADS = 4;

    AtomicInteger atomicInteger = new AtomicInteger();
    AtomicBoolean continueCalculation = new AtomicBoolean(true);
    final CyclicBarrier barrier;

    public static void main(String[] args) {
        new Solver();
    }

    class Worker implements Runnable {
        int workerId;
        Worker(int workerId) {
            this.workerId = workerId;
        }

        public void run() {
            try {
                while(continueCalculation.get()) {
                    calculate(workerId);
                    barrier.await();
                }

            } catch (Exception ex) {
                System.out.println("Finishing " + workerId);
            }
        }
    }

    public Solver() {
        Runnable barrierAction = () -> {
            if (done()) {
                continueCalculation.set(false);
            }
        };

        barrier = new CyclicBarrier(NUMBER_OF_THREADS, barrierAction);

        List<Thread> threads = new ArrayList(NUMBER_OF_THREADS);
        for (int i = 0; i < NUMBER_OF_THREADS; i++) {
            Thread thread = new Thread(new Worker(i));
            threads.add(thread);
            thread.start();
        }
    }

    private void calculate(int workerId) throws InterruptedException {
        // Some long-running calculation
        Thread.sleep(2000L);
        int r = new Random().nextInt(12);

        System.out.println("Worker #" + workerId + " added " + r +" = " + atomicInteger.addAndGet(r));
    }

    private boolean done() {
        int currentResult = atomicInteger.get();
        boolean collected = currentResult >= REQUIRED_AMOUNT;

        System.out.println("=======================================================");
        System.out.println("Checking state at the barrier: " + currentResult);
        if (collected) {
            System.out.println("Required result is reached");
        }
        System.out.println("=======================================================");

        return collected;
    }
}

Concordinating threads with a CyclicBarrier, The CyclicBarrier is generally more useful than CountDownLatch in cases where: a multithreaded operation occurs in stages or iterations, and;; a single-threaded  CyclicBarrier was introduced in Java 5 with other concurrency utils such as CountDownLatch, ConcurrentHashMap and BlockingQueue. CyclicBarrier is synchronized aid which allows set of threads to wait for each other at common barrier points.It is called cyclic because it can be reused once waiting threads are released.

CyclicBarrier in Java, A CyclicBarrier is a synchronizer that allows a set of threads to wait for each other to reach a common execution point, also called a barrier. The first use case of CyclicBarrier is to signal that we are ready to proceed and wait for the other threads. The class DistributedTxCommitTask from the Blazegraph open source graph database uses

Java.util.concurrent.CyclicBarrier Example, Java.util.Concurrent.CyclicBarrier is a synchronisation aid that allows a So in our example the 2 services and the main thread calling them  The java.util.concurrent package contains several classes that help manage a set of threads that collaborate with each other. Some of these include: CyclicBarrier; Phaser; CountDownLatch; Exchanger; Semaphore; SynchronousQueue; These classes offer out of the box functionality for common interaction patterns between threads.

CyclicBarrier example, The barrier is called cyclic because it can be re-used after the waiting threads are released. In order to create and use the CyclicBarrier we have  When you create a CyclicBarrier you specify how many threads are to wait at it, before releasing them. Here is how you create a CyclicBarrier: CyclicBarrier barrier = new CyclicBarrier(2); Waiting at a CyclicBarrier. Here is how a thread waits at a CyclicBarrier: barrier.await(); You can also specify a timeout for the waiting thread.

Comments
  • Stick a while(true) into the Thread. await() the barrier at the end of the loop. When the all the threads are done then reset() the barrier and the whole lot begins again...