views:

347

answers:

3

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.

+1  A: 

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();
Chandru
Still doesn't wait for both the programs to finish before exiting. Is there an explicit way I can say, wait till both thread1 and thread2 finish?
Ritesh M Nayak
Yup, can do. Thread.join() is there for that.
mlaverd
If you want a truly async wait for the threads' completion why bother if the method exits before their completion? Generally you'd want to do something when both the threads finish execution. Just put that in the callback to CyclicBarrier and you are good to go.
Chandru
+2  A: 

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

pgras
But this is tricky because if thread1.join() doesn't happen then thread2.join() will wait infinitely. The reason I chose CyclicBarrier is because it seems truly asynchronous in its wait.
Ritesh M Nayak
@Ritesh but if thread1.join won't happen for what are you waiting then? whats your usecase? do you need an "EITHER thread1 OR thread2 finished" implementation? pgras shows how to implement 'wait until both finished'
Karussell
@Ritesh, Either you want to wait for both `thread1` and `thread2` to exit (in which case this answer is correct), or you do not (in which case the version in the question is correct.)
finnw
@finnw There is a case where you don't really want to block all the remaining operations in current thread but only some of them needs to be done after the barrier.
Chandru
@Chandru, then you probably want an extra worker thread
finnw
My use case is that I want both thread1.join() and thread2.join to work. I tried this out and it works, what happens when thread1 throws an exception, does the join method stil work?
Ritesh M Nayak
@Ritesh yes, `thread1.join()` returns normally if `thread1` terminates due to an exception. `join()` throws only if the calling thread is interrupted. It does not (unlike `Future.get()`) propagate exceptions from the worker thread to the calling thread.
finnw
+4  A: 

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.

Tadeusz Kopec
However, this one makes it synchronous while the OP seems to want a truly asynchronous approach.
Chandru
@Chandru: Well, either "Should wait till both threads finish executing before printing this" or asynchronous. You can't wait asynchronously.
Tadeusz Kopec
If I understand it correctly, what he needs is to print that line after the 2 threads complete their job, which can be achieved by doing it in the barrier action. This way if there are other operations in the current thread which don't depend on completion of the other 2 threads, they can continue. BTW I was not the one who down-voted you. It is still a valid solution if all other operations in current thread depended on the 2 threads' completion.
Chandru
Thank you guys. I have learn't a lot more on threads thanks to this question. A small question though. Why is extending Thread not a good option?
Ritesh M Nayak