开发者

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.


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.


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();


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


Cyclic barrier is not the correct choice in this case. You must use CountDownLatch here.

I assume you have are invoking spawnAndWait method from the main method.

The reason this wont work is that the CyclicBarrier has 2 constructors. To perform post-operations you must use a 2 parameter constructor. The most important thing to remember is that the main thread will not wait by the await method; but will continue to execute. However the Thread specified in the CyclicBarrier constructor will only run when all spawned threads stop at the barrier(by the await method)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜