Java wait()方法的行为

Java wait()方法的行为,java,multithreading,Java,Multithreading,假设令牌机一次只能发出一个令牌。规则是必须先使用一个令牌,然后才能创建另一个令牌 class TokenMachine { private int tokenID; private boolean tokenExists = false; public synchronized void createToken(int coup){ ... } public synchronized int consumeToken(){ ...

假设令牌机一次只能发出一个令牌。规则是必须先使用一个令牌,然后才能创建另一个令牌

class TokenMachine {
    private int tokenID;
    private boolean tokenExists = false;
    public synchronized void createToken(int coup){
      ...
    }
    public synchronized int consumeToken(){
      ...
    }
}

public synchronized void createToken(int coup) {
    while(tokenExists) { //can I change 'while' to 'if'?
        wait(); //in a try-catch block
    }
    this.tokenID = coup;
    tokenExists = true;
    notify();
}

public synchronized int consumeToken() {
    while(!tokenExists) { //can I change 'while' to 'if'?
        wait(); //in a try-catch block
    }
    tokenExists = false;
    notify();
    return tokenID;
}
我的问题是,我可以在不破坏规则的情况下,将以前代码中的“while”表达式改为“if”吗?非常感谢

感谢各位回答我的问题,我在网上查了很多,发现以下信息很有帮助: 线程也可以在不被通知、中断或超时的情况下唤醒,即所谓的虚假唤醒。虽然这种情况在实践中很少发生,但应用程序必须通过测试本应导致线程被唤醒的条件来防范这种情况,并在条件不满足时继续等待。换句话说,等待应该总是在循环中发生


显然,虚假唤醒是一个问题(我怀疑这是一个众所周知的问题),中级到专家级的开发人员知道它可能发生,但它刚刚在JLS第三版中得到澄清,该版本已作为JDK 5开发的一部分进行了修订。JDK 5中的javadoc of wait方法也已更新

您需要使用
while
以避免在出现问题时唤醒线程。在虚假唤醒的情况下,可以在不调用
notify()
的情况下唤醒线程。
while
循环将重新检查条件,并且仅当它是真正的
notify
调用而不是虚假的重新激活时才继续。您需要使用
while
以避免在发生错误时唤醒线程。在虚假唤醒的情况下,可以在不调用
notify()
的情况下唤醒线程。
while
循环将重新检查条件,仅当它是真正的
notify
调用而不是虚假的重新激活时,才会继续进行。

类令牌机器{
class TokenMachine {
  ArrayBlockingQueue<Integer> q=new ArrayBlockingQueue<Integer>(1);

  public synchronized void createToken(int coup){
    q.put(coup);
  }

  public synchronized int consumeToken(){
    return q.get();
  }
}
ArrayBlockingQueue q=新的ArrayBlockingQueue(1); 公共同步的void createToken(int-coup){ q、 政变; } 公共同步int consumeToken(){ 返回q.get(); } }
类令牌机{
ArrayBlockingQueue q=新的ArrayBlockingQueue(1);
公共同步的void createToken(int-coup){
q、 政变;
}
公共同步int consumeToken(){
返回q.get();
}
}

您最好使用
notifyAll()
,因为您当前引入了一种可能性,即如果“错误”线程被
notify()
唤醒,则所有线程都将无限期等待。谢谢标记,在调用notify()之后,我仍然不明白执行notify()的当前线程会发生什么情况方法?通知线程将继续运行,被通知线程将等待获取监视器(就好像它们在同步块的开始),直到通知线程退出同步块并释放监视器。但是我建议读一本关于Java并发性的好书,它太复杂了,无法在注释中解释。你最好使用
notifyAll()
,因为你现在引入了一种可能性,如果“错误”线程被
notify()
唤醒,那么所有线程都将无限期等待。谢谢马克,我还是不明白,调用notify()后,执行notify()方法的当前线程会发生什么情况?通知线程将继续运行,并且被通知的线程将等待获取监视器(就好像它们位于同步块的开头),直到通知线程退出同步块并释放监视器。但是我建议读一本关于Java并发性的好书,它太复杂了,无法在注释中解释。谢谢Hari,我仍然不明白,在调用notify()之后,执行notify()方法的当前线程发生了什么?它只是继续做它正在做的事情。谢谢Hari,我仍然不明白,在调用notify()之后执行notify()方法的当前线程会发生什么情况?它只是继续执行它正在执行的任何操作。