2009-04-21 13 views
1

Ich habe eine Klasse namens Communicator. Diese Klasse ist ein Listener eines Threads, der Ereignisse von einem anderen Programm empfängt. Auch diese Klasse hat eine Methodenaufrufaktualisierung, die sendet und eine Aktion an das Programm a wartet auf die Antwort, die durch den Listener kommt.Wie mit Java-Threads umgehen

Beide Methoden sind in der gleichen Klasse, aber von verschiedenen Threads aufgerufen.

public void processRefreshEvent(ManagerEvent event){ 
    //processing event 
    //... 
    //I'm done 
    notify(); 
} 


public synchronized void refresh() throws Exception { 
    isRefreshing = true;  
    try { 
        manager.send(new refresh()); 
    } catch (ManagerException e) { 
     isRefreshing = false; 
    } 

    try { 
      wait(5000); 
    } catch (InterruptedException e) { 
    } finally{ 
     isRefreshing = false; 
    } 
} 

bei der Ausführung des Codes oben ich die Folge Ausnahme erhalten:

java.lang.IllegalMonitorStateException: current thread not owner 
     at java.lang.Object.wait(Native Method) 
     at Communicator.refresh(Communicator.java:203) 
     ... 

Was ist der richtige Weg ist, „warten“ für einen anderen Thread zu beenden. Vielen Dank.

Antwort

2

Sie müssen Ihre Threads auf einem Monitor synchronisieren. Zum Beispiel (unter Verwendung des aktuellen Objekts als Monitor):

public void processRefreshEvent(ManagerEvent event){ 
     //processing event 
     //... 
     //I'm done 
    synchronized(this) { 
     notify(); // you are basically notifying any thread who has blocked 
        // on this monitor - in our case, the instance of this object 
    } 
} 


public synchronized void refresh() throws Exception { 
     isRefreshing = true;  
     try { 
        manager.send(new refresh()); 
     } catch (ManagerException e) { 
       isRefreshing = false; 
     } 

     try { 
      synchronized(this) { 
       wait(5000); // wait will give up the monitor 
      } 
     } catch (InterruptedException e) { 
     } finally{ 
       isRefreshing = false; 
     } 
} 
+0

Nur um klar zu sein, bedeutet "jeder Thread" "eine der wartenden Threads" nicht "alle wartenden Threads". – erickson

+0

Beachten Sie auch, dass der wartende Thread aus eigenem Antrieb aufwachen kann. –

0

Von Object.wait() ‚s JavaDocs: " Der aktuelle Thread dieses Objekts Monitor besitzen muss" Sie müssen also auf das Objekt synchronisieren, das Sie aufrufen, warten Sie auf.

Alternativ könnten Sie BlockingQueue verwenden, die Collection und Queue implementiert. BlockingQueue macht die ganze Arbeit von warten und benachrichtigen. Ihr Thread kann einfach take() anrufen, der solange blockiert, bis Daten verfügbar sind. Mit den verschiedenen Einfügemethoden (add, put, etc) fügen Sie der Warteschlange Daten hinzu. BTW die Einfügemethoden rufen notify während take() Anrufe wait.

1

Die Methoden wait() und notify() dürfen nur von einem Thread aufgerufen werden, der momentan auf ihrer Instanz synchronisiert ist.

Deklarieren „processRefreshEvent“ synchronized, oder besser noch, nur die Code-Block, der den Zustand ändert, der durch die refresh Verfahren verwendet wird, zusammen mit dem Aufruf notify().

public void processRefreshEvent(ManagerEvent event){ 
    // processing event 
    synchronized (this) { 
    // modify shared state with results of processing. 
    notify(); 
    } 
} 
0

Bitte lesen Sie die JavaDoc auf java.lang.Object.wait() und notify().

Sie sollten die wait() mit dem richtigen Monitor, in diesem Fall synchronisieren:

try{ 
    synchronized(this){ 
      wait(5000); 
    } 
} 
catch (InterruptedException e) { 
} finally{ 
      isRefreshing = false; 
} 
1

Sie sagen, Sie, bis ein anderer Thread beendet hat, warten soll? Rufen Sie dann join() für das Thread-Objekt auf, auf das Sie warten möchten.

Verwandte Themen