2012-05-01 8 views
5

Ist es nicht möglich, dass notify() in einem anderen Thread vor dem wait() in einem Thread aufgerufen wird? Es passiert mit mir.Java notify() wird vor wait() aufgerufen

Ein Client fordert einen Wert von einem Ziel an und wartet auf eine Ergebnisvariable RV. Falls das Ziel der Client selbst ist, aktualisiere ich RV mit dem korrekten Ergebnis und rufe notify() auf RV in einem anderen Thread auf.

class EMU { 

    ResultVar RV; 
    Address my_address; 

    ResultVar findValue(String key) { 
    String tgt = findTarget(key); 
    sendRequest(tgt, key); 
    synchronized(RV) { 
     RV.wait(); 
    } 

    return RV; 
    } 

    Runnable Server = new Runnable() { 
    public void run() { 
     //code to receive connections. Assume object of type Request is read from the stream. 
     Request r = (Request) ois.readObject(); 
     if(r.requesterAddr.compareTo(my_address) == 0) { 
     String val = findVal(key); 
     RV.putVal(val); 
     synchronized(RV){ 
      RV.notify(); 
     } 
     } 
    } 
    }; 
} 

Das Problem ist, dass, bevor der Antragsteller alle „Networking“ (sendReqest in dem obigen Beispiel) mit sich selbst abgeschlossen ist, wird das Ergebnis in der Ergebnisvariablen aktualisiert. Wenn der Requester-Thread nun wait() aufruft, wird das Programm nicht fortgesetzt, da notify bereits aufgerufen wurde.

Wie können wir das verhindern?

+1

'Falls das Ziel ist der Kunde itself' Was meinst du denn hier? Können Sie ein Codebeispiel hinzufügen? – Cratylus

+1

@shishir garg könnten Sie bitte etwas Code einfügen –

+0

Ohne den Code zu sehen ist es schwierig zu beantworten - 2 Kommentare obwohl: a) es ist im Allgemeinen besser, NotifyAll zu verwenden, anstatt zu benachrichtigen, es sei denn Sie wissen, was Sie tun b) mit warten und notify kann fehleranfällig sein und Sie sollten die API für Parallelität auf höherer Ebene verwenden, sofern Sie nicht etwas sehr Spezifisches benötigen. – assylias

Antwort

4

Nichts hält Sie notify auf einem Objekt aufrufen, die von einem anderen Thread ed nicht wait sein wird.

Es klingt wie, was Sie wollen, ist eine Wartezeit nur, wenn eine Bedingung erfüllt ist. Zum Beispiel:

synchronized (results) { 
    while (!results.hasResults()) { 
     // no results yet; wait for them 
     try { 
      results.wait(); 
     } catch (InterruptedException ie) { /* ignore */ } 
    } 
} 
1

Ich würde dringend empfehlen, das Rad nicht neu zu erfinden.

Die Java-Schnittstelle Future wurde für Ergebnisse entwickelt, die möglicherweise erst später eintreffen, und die Klasse FutureTask implementiert diese Schnittstelle.

Lassen Sie den ersten Thread Zugriff auf die Zukunft und erhalten Sie den zweiten Thread, um die FutureTask auszuführen, und all das Zeug wird für Sie behandelt. Sie erhalten auch Timeout-Unterstützung kostenlos.

0

Verwenden einige Zustand vor() warten werde und stellen Sie sicher, dass diese Bedingung Thread-sicher ist :)

class EMU{ 
    ResultVar RV; 
    Address my_address; 
    volatile boolean condition = true; 

    ResultVar findValue(String key){ 
     String tgt = findTarget(key); 
     sendRequest(tgt, key); 
     synchronized(RV){ 
      while(condition == true) 
      { 
       RV.wait(); 
      } 
     } 
     return RV; 
    } 

    Runnable Server = new Runnable(){ 
     public void run(){ 
      //code to receive connections. Assume object of type Request is read from the stream. 
      Request r = (Request) ois.readObject(); 
      if(r.requesterAddr.compareTo(my_address) == 0){ 
       String val = findVal(key); 
       RV.putVal(val); 
       synchronized(RV){ 
        condition = false; 
        RV.notify(); 
       } 
      } 
     } 

    }; 
Verwandte Themen