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)
精彩评论