Лучший способ ждать на Яве - PullRequest
4 голосов
/ 23 февраля 2012

У меня есть приложение, которое должно ждать какое-то неизвестное количество времени. Он должен ждать, пока несколько полей данных не будут заполнены сервером.

API сервера предоставляет мне способ запрашивать данные, достаточно просто ...

API сервера также предоставляет способ получения моих данных по одному полю за раз. Он не сообщает мне, когда все поля будут заполнены.

Какой самый эффективный способ дождаться окончания обработки моего запроса сервером? Вот некоторый псевдокод:

public class ServerRequestMethods {
    public void requestData();
}

public interface ServerDeliveryMethods {
    public void receiveData(String field, int value);
}

public class MyApp extends ServerRequestMethods implements ServerDeliveryMethods {
    //store data fields and their respective values
    public Hashtable<String, Integer> myData;    

    //implement required ServerDeliveryMethods
    public void receiveData(String field, int value) {
        myData.put(field, value);    
    }

    public static void main(String[] args) {
        this.requestData();

        // Now I have to wait for all of the fields to be populated,
        // so that I can decide what to do next.

        decideWhatToDoNext();
        doIt();
    }
}

Мне нужно подождать, пока сервер не заполнит мои поля данных, и сервер не сообщит мне, когда запрос будет выполнен. Поэтому я должен продолжать проверять, завершил ли мой запрос обработку. Какой самый эффективный способ сделать это?

wait () и notify (), с методом, защищающим цикл while, который проверяет, есть ли у меня все необходимые значения, но каждый раз, когда я просыпаюсь notify ()?

Observer и Observable, с методом, который проверяет, есть ли у меня все необходимые значения, но каждый раз, когда вызывается мой Observer.Update ()?

Какой лучший подход? Благодарю.

Ответы [ 5 ]

5 голосов
/ 23 февраля 2012

Если я вас правильно понял, какой-то другой поток вызывает receiveData на вашем MyApp для заполнения данных.Если это правильно, то вот как вы это делаете:

  1. Вы спите так:

    do {
        this.wait(someSmallTime); //We are aquiring a monitor on "this" object, so it would require a notification. You should put some time (like 100msec maybe) to prevent very rare but still possible deadlock, when notification came before this.wait was called.
    } while (!allFieldsAreFilled());
    
  2. receiveData должен составить notifyпозвони на unpause этот wait твой звонок.Например, вот так:

    myData.put(field, value);   
    this.notify();
    
  3. Оба объекта должны быть "синхронизированы" на this объекте, чтобы иметь возможность получить его монитор (это необходимо для wait).Вам нужно либо объявить методы как «синхронизированные», либо поместить соответствующие блоки в блок synchronized(this) {...}.

3 голосов
/ 23 февраля 2012
1 голос
/ 23 февраля 2012

Я думаю, что самый эффективный метод - это ждать и уведомлять. Вы можете перевести Thread в режим сна с помощью wait(). Вы можете разбудить Нить от другого, например, ваш сервер с notify(), чтобы проснуться. wait() - это метод блокировки, вам не нужно ничего опрашивать. Вы также можете использовать статический метод Thread.sleep(milliseconds), чтобы подождать некоторое время. Если вы поместите сон в бесконечный цикл проверки состояния с непрерывным временем ожидания, вы также будете ждать.

Я предпочитаю wait() и notify(), это самый эффективный из всех.

0 голосов
/ 23 января 2018

Довольно старый вопрос, но я искал похожую проблему и нашел решение.
Сначала разработчик никогда не должен создавать поток, который будет ждать вечно.Вы действительно должны создать «условие выхода», если используете цикл «пока».Кроме того, ожидание InterruptedException сложно.Если другой поток не вызывает yourThread.interrupt (), вы будете ждать, пока программа действительно завершится.Я использовал java.util.concurrent.CountDownLatch так коротко:

/*as field*/
CountDownLatch semaphore = new CountDownLatch(1);

/*waiting code*/
boolean timeout = !semaphore.await(10, TimeUnit.SECONDS);

/*releasing code*/
semaphore.countDown();

В результате поток «ожидающего кода» будет ждать, пока какой-то другой поток не вызовет «освобождающий код» или не будет «истек».Если вы хотите дождаться заполнения 10 полей, используйте «new CountDownLatch (10)».
Этот принцип похож на «java.util.concurrent.Semaphore», но семафор лучше для блокировки доступа, и это не так »Твой случай, действительно.

0 голосов
/ 19 августа 2013

Кажется, что у многих людей были проблемы с этим (включая меня), но я нашел простое и гладкое решение.Используйте этот метод:

public static void delay(int time) {
    long endTime = System.currentTimeMillis() + time;
    while (System.currentTimeMillis() < endTime) 
    {
        // do nothing
    }
}

Получает текущее время и устанавливает время окончания (текущее время + время ожидания) и ждет, пока текущее время не достигнет времени окончания.

...