java - 调用notifyAll的最佳解决方案是什么?

原文 标签 java multithreading wait notify

我有一个关于wait()和notifyAll()方法的问题。
该代码正在模拟两个线程的“竞赛”。

让我们看一下代码-问题在于,notifyAll()方法对等待的线程不执行任何操作,导致main方法首先获得了锁...简单的解决方法是设置一些延迟(请参见注释行)。但这是一个坏习惯。这个问题有什么好的解决方案?我只想使用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()时,您需要更改一个状态,而在waiting()中时,您需要循环检查该状态。如果你不这样做


notifyAll()仅通知正在等待的线程,而不通知稍后开始等待的线程。
wait()可能会虚假地唤醒。


在这种情况下,最简单的解决方案就是不用担心。您正在等待最多100毫秒的随机延迟,因此尝试同步这样一个随机系统的启动非常困难。

我认为循环退出时“竞赛结束”,您不需要if子句。

相关文章:

java - 构建路径中的必需项目[Eclipse]

java - JavaFX 2.1和线程? -或-优雅地结束JavaFX应用程序?

java - 如何使程序等待设定的时间? [重复]

java - Hibernate MappingException未知实体

java - 创建数据库时出现SQLiteException-“ android”附近的SQLiteException

java - 如果我们创建子类的对象,会不会有父类的对象创建?

java - Java-用循环填充线程的ArrayList

multithreading - Delphi-线程中的消息泵未接收到WM_COPYDATA消息

android - android:暂停活动,直到另一个完成

asynchronous - 颤动,功能需要等到数据可用