调用notifyAll的好方法是什么?

调用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; 
} 
+1

您的决定使用等待/通知是一个糟糕的。你需要围绕这些原始图元进行更多的编程才能获得可靠的行为。对于初学者,你必须*等待条件*,而不是原始的'notifyAll'信号。这在整个网络中都有记录,例如[here](http://*.com/questions/1038007/why-should-wait-always-be-called-inside-a-loop)。 – 2013-05-06 14:07:59

当你调用notifyAll的(),您需要更改的状态,当你正在等待(),您需要检查在一个循环的状态。如果你不这样做

  • notifyAll()只通知正在等待()的线程,而不是线程开始等待稍后。
  • wait()可以虚假地唤醒。

在这种情况下,最简单的解决方案就是不用担心。您正在等待100毫秒的随机延迟,因此尝试同步这种随机系统的开始并不会产生很大的影响。

当循环结束时,我会认为“比赛已完成”,因此您不需要if子句。