2016-03-13 4 views
2

У меня есть поток, который работает в фоновом режиме моей программы и обнаруживает, когда наступает крайний срок (установленный пользователем в начале программы). Я реализовал это в цикле while и использовал метод sleep(1000).Java - использовать метод wait() до определенного времени

Это все работает нормально, но я хотел бы изменить его на от использования 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(), но успеха не имел. Может ли кто-нибудь увидеть способ изменения существующего кода для реализации упомянутых мной методов?

Спасибо заранее, Марк

+0

Где вы хотите позвонить? Почему бы вам просто не спать количество секунд, которое вам нужно, а не какие-то 1000? – matt

+0

notifyAll() не вызывается в настоящий момент, так как пока нет вызова wait(). В настоящий момент он проверяет каждую секунду, потому что крайний срок вводится на одну минуту, и я только что запускал его с проверкой каждую секунду. Я бы хотел использовать wait(), чтобы сделать его более точным @matt – marcuthh

+0

Я не понимаю, как ожидание сделает его более точным. Вероятно, вы должны использовать сон, который вам нужен, а не на 1 секунду. Таким образом, если бы вы были на пару миллисекунд на чеке, вы бы не подождали целую секунду, только пару миллисекунд. Если вы хотите сделать это правильно, используйте ScheduledExecutorService. – matt

ответ

0

Используйте метод wait(long timeout).

+0

Привет, как работает этот метод? Будет ли он просто ждать, пока не будет достигнут крайний срок, а затем выпадет из цикла while? – marcuthh

+0

@marcuthh он говорит, что он делает в javadoc. Обратите внимание, что это для работы с блокировкой. Если вы не блокируете объект, нет смысла «ждать» на нем. –

+0

См. Https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#wait-long- – aventurin

2

Так что это вопрос, как я могу использовать wait, чтобы действовать как sleep. Если вы хотите использовать wait, вам придется использовать два потока. Используйте ScheduledExecutorService (Tutorial).

ScheduledExecutorService executor = newSingleThreadScheduledExecutor(); 

Это можно сделать один раз и повторно использовать. В противном случае вы должны завершить работу исполнителя.

Мы установим наш крайний срок, чтобы быть x минут в будущем, используя Instant из современных java.time рамок (Tutorial).

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(); 
    } 
} 

Это в петле, на всякий случай, когда возникает побочный эффект. Он повторно выполняет задачу, на всякий случай, когда возникла ложная тревога, и в то же время другая задача была завершена и не разбудила поток, прежде чем поток снова вызвал ожидание.

Это выше немного языка в щеке. Действительно, если вы просто использовали следующее, это выглядело бы более «в реальном времени».

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

От оракула документации 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 
} 
Смежные вопросы