调用notifyAll的好方法是什么?
问题描述:
我有一个关于wait()和notifyAll()方法的小问题。 代码模拟两个线程的'Race'。调用notifyAll的好方法是什么?
让我们看看代码 - 问题在于notifyAll()方法对于等待线程不起任何作用,导致主要方法首先得到锁定...简单的解决方法是设置一些延迟(参见注释行) 。但这是一个不好的做法。这个问题有什么好的解决方法?我只想使用wait/notifyAll/join方法。
public class TestThreads {
public static void main(String[] args) throws InterruptedException {
System.out.println("_start main");
Object lock = new Object();
Thread t1 = new Thread(new Car("Red car", lock));
Thread t2 = new Thread(new Car("Black car", lock));
t1.start();
t2.start();
//Thread.sleep(10L);
synchronized (lock){
System.out.println("Let`s go!");
lock.notifyAll();
}
t1.join();
t2.join();
System.out.println("_exiting from main...");
}
}
class Car implements Runnable {
private final String name;
private final Object lock;
public Car(String name, Object lock) {
this.name = name;
this.lock = lock;
}
@Override
public void run() {
int distance = 100;
synchronized (lock){
try{
System.out.println(name + " waiting...");
lock.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
System.out.println(name + " started...");
while (distance != 0){
try{
Thread.sleep((long) (100 * Math.random()));
}catch (InterruptedException e){
e.printStackTrace();
break;
}
distance--;
if (distance % 20 == 0 && distance != 0){
System.out.println(name + " " + distance+ " miles left");
}
else if (distance == 0){
System.out.println(name + " finished race!!!");
}
}
System.out.println("_exiting from thread of " + name + " move simulation...");
}
}
PS。对不起,我的英语不好。
谢谢你的答案。 那么,这个解决方案更好吗?
public class TestThreads {
public static void main(String[] args) throws InterruptedException {
System.out.println("_start main");
LightSignal lock = new LightSignal();
Thread t1 = new Thread(new Car("Red car", lock));
Thread t2 = new Thread(new Car("Black car", lock));
t1.start();
t2.start();
synchronized (lock){
Thread.sleep(1000L);
lock.isGreen = true;
System.out.println("Let`s go!");
lock.notifyAll();
}
t1.join();
t2.join();
System.out.println("_exiting from main...");
}
}
class Car implements Runnable {
private final String name;
private final LightSignal lock;
public Car(String name, LightSignal lock) {
this.name = name;
this.lock = lock;
}
@Override
public void run() {
int distance = 100;
synchronized (lock){
try{
while (!lock.isGreen){
System.out.println(name + " waiting...");
lock.wait();
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
System.out.println(name + " started...");
while (distance != 0){
try{
Thread.sleep((long) (100 * Math.random()));
}catch (InterruptedException e){
e.printStackTrace();
break;
}
distance--;
if (distance % 20 == 0 && distance != 0){
System.out.println(name + " " + distance + " miles left");
}
}
System.out.println(name + " finished race!!!");
System.out.println("_exiting from thread of " + name + " move simulation...");
}
}
class LightSignal {
public boolean isGreen = false;
}
答
当你调用notifyAll的(),您需要更改的状态,当你正在等待(),您需要检查在一个循环的状态。如果你不这样做
- notifyAll()只通知正在等待()的线程,而不是线程开始等待稍后。
- wait()可以虚假地唤醒。
在这种情况下,最简单的解决方案就是不用担心。您正在等待100毫秒的随机延迟,因此尝试同步这种随机系统的开始并不会产生很大的影响。
当循环结束时,我会认为“比赛已完成”,因此您不需要if
子句。
您的决定使用等待/通知是一个糟糕的。你需要围绕这些原始图元进行更多的编程才能获得可靠的行为。对于初学者,你必须*等待条件*,而不是原始的'notifyAll'信号。这在整个网络中都有记录,例如[here](http://*.com/questions/1038007/why-should-wait-always-be-called-inside-a-loop)。 – 2013-05-06 14:07:59