Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the java.concurrency.CyclicBarrier to work as expected

I am writing code that will spawn two thread and then wait for them to sync up using the CyclicBarrier class. Problem is that the cyclic barrier isn't working as expected and the main thread doesnt wait for the individual threads to finish. Here's how my code looks:

 class mythread extends Thread{
   CyclicBarrier barrier;
   public mythread(CyclicBarrier barrier) { 
       this.barrier = barrier;
      }

   public void run(){
            barrier.await();
       } 
 }



class MainClass{
 public void spawnAndWait(){
    CyclicBarrier barrier = new CyclicBarrier(2);
    mythread thread1 = new mythread(barrier).start();
    mythread thread2 = new mythread(barrier).start();
    System.out.println("Should wait till both threads finish executing before printing this");
  }
}

Any idea what I am doing wrong? Or is there a better way to write these barrier synchronization methods? Please help.

like image 359
Ritesh M Nayak Avatar asked Mar 26 '10 09:03

Ritesh M Nayak


3 Answers

During execution of your main thread you create two other threads and tell them to wait for each other. But you wrote nothing to make your main thread to wait for them and complain it doesn't wait. Try

CyclicBarrier barrier = new CyclicBarrier(3);
mythread thread1 = new mythread(barrier).start();
mythread thread2 = new mythread(barrier).start();
barrier.await(); // now you wait for two new threads to reach the barrier.
System.out.println("Should wait till both threads finish executing before printing this");

BTW. Don't extend Thread class unless you have to. Implement Runnable and pass implementations to Thread objects. Like this:

class MyRunnable implements Runnable {
    public void run(){
        // code to be done in thread
    }
}

Thread thread1 = new Thread(MyRunnable);
thread1.start();

EDIT
Justification for avoiding extending Thread.
The rule of thumb is as little coupling as possible. Inheritance is a very strong connection between classes. You have to inherit from Thread if you want to change some of its default behaviour (i.e. override some methods) or want to access some protected fields of class Thread. If you don't want it, you choose looser coupling - implementing Runnable and passing it as a constructor parameter to Thread instance.

like image 61
Tadeusz Kopec for Ukraine Avatar answered Nov 07 '22 23:11

Tadeusz Kopec for Ukraine


Pass a Runnable instance to the constructor of your CyclicBarrier like this.

CyclicBarrier barrier = new CyclicBarrier(2, new Runnable() {

    @Override
    public void run() {
        System.out.println("Should wait till both threads finish executing before printing this");
    }
});

new mythread(barrier).start();
new mythread(barrier).start();
like image 29
Chandra Sekar Avatar answered Nov 07 '22 22:11

Chandra Sekar


You are looking for Thread.join() method...

thread1.join();
thread2.join();
System.out.println("Finished");

EDIT: because of the comments...

And if you don't want to wait forever you can also specify the maximum number of milliseconds plus nanoseconds to wait for the thread to die

like image 41
pgras Avatar answered Nov 07 '22 22:11

pgras