2014-02-19 2 views
1

Я изо всех сил пытаюсь понять использование методов wait(), notify() и синхронных методов. У меня есть следующий пример, где он не работает. Некоторый другой объект вызывает dataHasChanged(), который изменяет значение переменной экземпляра datachanged на true. Затем, с notifyAll(), ожидающий поток проверяет значение datachanged. Все идет нормально. Но: значение datachanged равно false при регистрации в while(!datachanged). Итак, я полагаю, datachanged = true как-то не регистрируется с моим Refresher-Object. Что я делаю не так?Уведомление об ожидающем потоке при изменении переменной

public synchronized void dataHasChanged(){ 
    datachanged = true; 
    notifyAll(); 
} 

class Refresher extends SwingWorker<Void, Void>{ 

    public synchronized void refresh(){ 
     while(!datachanged){ 
      try { 
       wait(); 
      } catch (InterruptedException ex) { 
       Exceptions.printStackTrace(ex); 
      } 
     } 
     setRights(); 
     datachanged = false;    
    } 

    @Override 
    protected Void doInBackground() throws Exception { 
     refresh(); 
     return null; 
    } 

    @Override 
    protected void done() { 
     refresher = new Refresher(); 
     refresher.execute(); 
    } 


} 
+0

Обратите внимание, что 'notifyAll()' вызывается на 'this'. В вашем 'dataHasChanged()' это другой объект, чем в 'refresh()'. Также подумайте о том, чтобы сделать 'datachanged'' volatile'. –

+0

Сколько потоков у вас есть (с помощью функции refresh()) и как вы определили «datachanged»? –

+0

@Andreas M. На один экземпляр внешнего класса работает только одна Refresher-Thread. datachanged - частный volatile Boolean. –

ответ

2

wait(), notify(), notifyAll() и синхронизировать работу по одному объекту. В вашем случае refresh() ждет экземпляр Refresh и notifyAll() уведомляет все объекты, ожидающие экземпляра вашего внешнего класса. Для этого нужно работать как wait(), так и notifyAll(), которые должны быть вызваны на один и тот же объект (так что synchronized()).

Следующее выполняет все операции над экземпляром вашего внешнего класса.

public void refresh(){ 
    synchronized(WhateverYourOuterClass.this){ 
     while(!datachanged){ 
      try { 
       WhateverYourOuterClass.this.wait(); 
      } catch (InterruptedException ex) { 
       Exceptions.printStackTrace(ex); 
      } 
     } 
     setRights(); 
     datachanged = false;    
    } 
} 
+0

То есть. Спасибо, что освободил меня –

Смежные вопросы