我正在编写将产生两个线程的代码,然后等待它们使用CyclicBarrier类进行同步。问题是循环障碍没有按预期工作,主线程不等待各个线程完成。以下是我的代码的外观:
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");
}
}
知道我做错了什么吗?或者有更好的方法来编写这些屏障同步方法吗?请帮忙。
答案 0 :(得分:14)
在执行主线程期间,您创建另外两个线程并告诉它们彼此等待。但你没有写任何东西让你的主线程等待他们并抱怨它不等待。尝试
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");
顺便说一句。除非必须,否则不要扩展Thread类。实现Runnable并将实现传递给Thread对象。像这样:
class MyRunnable implements Runnable {
public void run(){
// code to be done in thread
}
}
Thread thread1 = new Thread(MyRunnable);
thread1.start();
修改强>
避免延长线程的理由
经验法则是尽可能少的耦合。继承是类之间非常强大的连接。如果要更改其某些默认行为(即重写某些方法)或想要访问Thread类的某些受保护字段,则必须从Thread继承。如果你不想要它,你选择更宽松的耦合 - 实现Runnable并将它作为构造函数参数传递给Thread实例。
答案 1 :(得分:2)
将Runnable
个实例传递给CyclicBarrier
的构造函数。
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();
答案 2 :(得分:2)
您正在寻找Thread.join()方法......
thread1.join();
thread2.join();
System.out.println("Finished");
编辑:因为评论...
如果您不想永远等待,您还可以指定等待线程死亡的最大毫秒数加上纳秒数
答案 3 :(得分:1)
在这种情况下,循环屏障不是正确的选择。您必须在此处使用CountDownLatch
。
我假设您正在从main方法调用spawnAndWait
方法。
这不起作用的原因是CyclicBarrier
有2个构造函数。要执行后期操作,必须使用2参数构造函数。要记住的最重要的事情是主线程不会等待await
方法;但会继续执行。但是,CyclicBarrier
构造函数中指定的线程仅在所有生成的线程停在屏障处时运行(通过await
方法)