новичок в многопоточности - как использовать wait() и notify() в java?

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

//in controller:
Calculator calc=new Calculator();
calc.runCalculations(data);
while(calc.isCalculating()){
    //do nothing
}
System.out.println("results: "+calc.getAnswer());
calc.runCalculations(data2);

//in calculator:
public runCalculations(Data data){
    globalData=data;
    this.notify();
}
public void run(){
    while(true){
        synchronized(this){
            wait();
        }
        calculating=true;
        globalData=calculate(globalData);
        calculating=false;
    }
}

person Eric Fitting    schedule 19.07.2010    source источник


Ответы (1)


Вам нужно получить монитор на this, прежде чем звонить notify(). Кроме того, когда вы вызываете wait(), вы должны делать это в цикле, который проверяет условие, чтобы убедиться, что вы не испытали ложного пробуждения.

public runCalculations(Data data){
    globalData=data;
    synchronized(this) {
        calculating=true;
        this.notify();
    }
}
public void run(){
    while(true){
        synchronized(this){
            calculating=false;
            while(!calculating) {
                wait();
            }
        }
        globalData=calculate(globalData);
    }
}

В общем, большинство людей советуют не использовать ожидание/уведомление и вместо этого рекомендуют использовать Executor или, по крайней мере, BlockingQueue. Но оба из них потребуют от вас перепроектирования того, что вы сейчас думаете.

person Tim Bender    schedule 19.07.2010
comment
Позвольте мне присоединиться к большинству людей и посоветовать не использовать низкоуровневые примитивы синхронизации потоков, а вместо этого использовать пакет concurrency. По крайней мере, взгляните на BlockingQueue, чтобы понять, нравится ли вам это. - person Thilo; 19.07.2010