Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Electing a thread for barrier action execution - Java CyclicBarrier

Looking at the javadocs for CyclicBarrier I found the following statement in the class documentation that I dont completely understand. From the javadoc:

If the barrier action does not rely on the parties being suspended when it is executed, then any of the threads in the party could execute that action when it is released. To facilitate this, each invocation of await() returns the arrival index of that thread at the barrier. You can then choose which thread should execute the barrier action, for example:

if (barrier.await() == 0) {
  // log the completion of this iteration
} 

Can someone explain how to designate a specific thread for execution of the barrier action once all the parties have called .await() and perhaps provide an example?

like image 331
Brad Yoo Avatar asked Dec 23 '11 20:12

Brad Yoo


1 Answers

OK, pretend RuPaul wanted some worker threads, but only the 3rd one that finished is supposed to do the barrier task (Say "Sashay, Chante").

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;

public class Main
{

   private static class Worker implements Runnable {

      private CyclicBarrier barrier;

      public Worker(CyclicBarrier b) {
         barrier = b;
      }

      public void run() {
         final String threadName = Thread.currentThread().getName();

         System.out.printf("%s:  You better work!%n", threadName);
         // simulate the workin' it part
         Random rnd = new Random();
         int secondsToWorkIt = rnd.nextInt(10) + 1;

         try {
            TimeUnit.SECONDS.sleep(secondsToWorkIt);
         } catch (InterruptedException ex) { /* ...*/ }

         System.out.printf("%s worked it, girl!%n", threadName);

         try {
            int n = barrier.await();
            final int myOrder = barrier.getParties() - n;
            System.out.printf("Turn number: %s was %s%n", myOrder, threadName);

            // MAGIC CODE HERE!!!
            if (myOrder == 3) { // the third one that finished
               System.out.printf("%s: Sashay Chante!%n", myOrder);
            }
            // END MAGIC CODE
         }
         catch (BrokenBarrierException ex) { /* ... */ }
         catch (InterruptedException ex) { /* ... */ }
      }
   }

   private final int numThreads = 5;

   public void work() {
      /*
       * I want the 3rd thread that finished to say "Sashay Chante!"
       * when everyone has called await.
       * So I'm not going to put my "barrier action" in the CyclicBarrier constructor,
       * where only the last thread will run it! I'm going to put it in the Runnable
       * that calls await.
       */
      CyclicBarrier b = new CyclicBarrier(numThreads);

      for (int i= 0; i < numThreads; i++) {
         Worker task = new Worker(b);
         Thread thread = new Thread(task);
         thread.start();
      }
   }

   public static void main(String[] args)
   {
      Main main = new Main();
      main.work();
   }

}

Here is an example of the output:

Thread-0:  You better work!
Thread-4:  You better work!
Thread-2:  You better work!
Thread-1:  You better work!
Thread-3:  You better work!
Thread-1 worked it, girl!
Thread-4 worked it, girl!
Thread-0 worked it, girl!
Thread-3 worked it, girl!
Thread-2 worked it, girl!
Turn number: 5 was Thread-2
Turn number: 3 was Thread-0
3: Sashay Chante!
Turn number: 1 was Thread-1
Turn number: 4 was Thread-3
Turn number: 2 was Thread-4

As you can see, the thread that finished 3rd was Thread-0, so Thread-0 was the one that did the "barrier action".

Say you are able to name your threads:

thread.setName("My Thread " + i);

Then you can perform the action on the thread of that name...I don't know how feasible that is for you.

like image 109
black panda Avatar answered Sep 28 '22 02:09

black panda