为了账号安全,请及时绑定邮箱和手机立即绑定

Java中是否有一个“直到条件变为真”的功能?

Java中是否有一个“直到条件变为真”的功能?

慕哥9229398 2019-11-27 14:24:41
我正在为服务器编写侦听器线程,此刻我正在使用:while (true){    try {        if (condition){            //do something            condition=false;        }        sleep(1000);    } catch (InterruptedException ex){        Logger.getLogger(server.class.getName()).log(Level.SEVERE, null, ex);    }}使用上面的代码,我遇到了运行功能吃掉所有cpu时间循环的问题。睡眠功能有效,但似乎是临时解决方案,而不是解决方案。是否有一些函数会阻塞直到变量“ condition”变为“ true”?还是连续循环等待变量值改变的标准方法?
查看完整描述

3 回答

?
慕村225694

TA贡献1880条经验 获得超4个赞

这样的轮询绝对是最不受欢迎的解决方案。


我假设您有另一个线程将做一些事情来使条件成立。有几种同步线程的方法。在您的情况下,最简单的方法是通过对象发出通知:


主线程:


synchronized(syncObject) {

    try {

        // Calling wait() will block this thread until another thread

        // calls notify() on the object.

        syncObject.wait();

    } catch (InterruptedException e) {

        // Happens if someone interrupts your thread.

    }

}

其他线程:


// Do something

// If the condition is true, do the following:

synchronized(syncObject) {

    syncObject.notify();

}

syncObject本身可以很简单Object。


查看完整回答
反对 回复 2019-11-27
?
料青山看我应如是

TA贡献1772条经验 获得超8个赞

EboMike的答案和Toby的答案都在正确的轨道上,但是它们都有致命的缺陷。该缺陷称为丢失通知。


问题是,如果一个线程调用foo.notify(),它将根本不做任何事情,除非某个其他线程已经在foo.wait()调用中处于休眠状态。对象,foo不记得它已收到通知。


有一个原因导致不允许您调用,foo.wait()或者foo.notify()除非线程在foo上同步。这是因为避免丢失通知的唯一方法是使用互斥量保护条件。完成后,它看起来像这样:


使用者线程:


try {

    synchronized(foo) {

        while(! conditionIsTrue()) {

            foo.wait();

        }

        doSomethingThatRequiresConditionToBeTrue();

    }

} catch (InterruptedException e) {

    handleInterruption();

}

生产者线程:


synchronized(foo) {

    doSomethingThatMakesConditionTrue();

    foo.notify();

}

更改条件的代码和检查条件的代码都在同一对象上同步,并且使用者线程在等待之前显式测试条件。wait()当条件为真时,用户无法错过通知并永远陷入通话中。


另请注意,这wait()是一个循环。这是因为,在一般情况下,当使用者重新获取foo锁并唤醒时,其他一些线程可能再次使条件变为假。即使您的程序无法做到这一点,在某些操作系统中,foo.wait()即使foo.notify()没有被调用,也可能返回。这被称为“ 伪唤醒”,它被允许发生,因为它使等待/通知在某些操作系统上更容易实现。


查看完整回答
反对 回复 2019-11-27
  • 3 回答
  • 0 关注
  • 517 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信