Java - 使用wait()方法直到达到特定时间

时间:2016-03-13 20:34:11

标签: java multithreading wait

我有一个在我的程序后台运行的线程,并检测何时发生截止日期(由程序开头的用户输入设置)。我已在while循环中使用sleep(1000)方法实现了此功能。

这一切都运行正常,但我想将其从使用sleep(1000)更改为使用wait()notifyAll()以与我的其余代码保持一致,并将其更改为警报实时发生,而不是滞后一段时间,直到线程重新唤醒。

这是我目前拥有的

    //Retrieve current date and time...
    Calendar now = Calendar.getInstance();

    //deadline not yet reached
    while(now.before(deadline))
    {
        try
        {
            //wait a second and try again
            sleep(1000);
        }
        catch (InterruptedException intEx)
        {
            //Do nothing.
        }

        //Update current date and time...
        now = Calendar.getInstance();
        //run loop again
    }

    ////////////////////////////
    ///alert user of deadline///
    ////////////////////////////

我尝试将其更改为使用wait(),但没有成功。任何人都可以看到一种改变现有代码的方法来实现我提到的方法吗?

提前致谢, 标记

3 个答案:

答案 0 :(得分:4)

所以这个问题是,如何使用wait来表达sleep。如果要使用wait,则必须使用两个线程。使用ScheduledExecutorServiceTutorial)。

 ScheduledExecutorService executor = newSingleThreadScheduledExecutor();

这可以完成一次并重复使用。否则你必须关闭执行程序。

我们将使用现代Instant框架(java.time)中的Tutorial将截止日期设置为x分钟。

final Instant deadline = Instant.now().plus(x, ChronoUnit.MINUTES);

接下来,我们要安排一个任务,以便我们的线程在x分钟内唤醒。

while(Instant.now().isBefore(deadline)){
    synchronized(deadline){    
        executor.schedule(
            ()->{
                synchronized(deadline){
                    deadline.notifyAll();
                }
            }, 
            Duration.between(Instant.now(),deadline).toMillis(), 
            TimeUnit.MILLISECONDS
        );
        deadline.wait();
    }
}

这是一个循环,以防万一有虚假的清醒。它重新提交任务,以防万一有虚假的清醒,同时另一个任务完成,并且在线程再次调用wait之前没有唤醒线程。

这上面有点舌头。真的,如果你刚刚使用了以下内容,那么它似乎更像是实时的''。

long diff = deadline.getTimeInMillis()-now.getTimeInMillis();
if(diff>0)
    Thread.sleep(diff);

答案 1 :(得分:1)

来自oracle文档page

public final void wait(long timeout)
                throws InterruptedException
  

导致当前线程等待,直到另一个线程调用此对象的notify()方法或notifyAll()方法,或者已经过了指定的时间量。

前提条件: 当前线程必须拥有此对象的监视器。

线程也可以在没有被通知,中断或超时的情况下唤醒,即所谓的虚假唤醒。虽然这在实践中很少发生,但应用程序必须通过测试应该导致线程被唤醒的条件来防范它,并且如果条件不满足则继续等待。换句话说,等待应该总是出现在循环中,如下所示:

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait(timeout);
     ... // Perform action appropriate to condition
 }

答案 2 :(得分:0)

使用wait(long timeout)方法。