2012-06-08 15 views
6

Ich bin eine Web-Anwendung in Jboss Application Server laufen und ich versuche, eine Ereignisbasis Antwort vom Server zu implementieren.wait() auf Servlet wirft Exception

Um das zu erreichen, verwende ich .wait() und .notify() auf die Servlets-Klasse. Grundsätzlich gibt es eine Ajax-Anfrage, der Servlet blockt mit wait bis ein Ereignis auf dem Server ist und wenn ja, wird notify auf dem Servlet ausgelöst.

Das Problem ist, wenn ich warten Sie (1000 * 60) auf der Servlet ich:

Servlet.service() for servlet ProcessesServlet threw exception: java.lang.IllegalMonitorStateException 

Ist es sogar möglich, eine wait() auf einer HttpServlet Klasse zu tun?

Antwort

7

Bevor Sie auf ein Objekt warten, müssen Sie das Eigentum übernehmen.

Dies wird normalerweise mit einer synchronisierten Anweisung durchgeführt.

synchronized (obj) { 
     try { 
      obj.wait(someTime); 
     } catch (Throwable e) { 
      e.printStackTrace(); 
     } 
    } 
+0

und ich muss das gleiche tun, bevor Sie benachrichtigen? –

+0

[ja] (http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Object.html#notify()) –

+0

es gibt etwas, das ich nicht bekomme ... wenn ich Übernimm den Besitz mit dem Thread, der .wait aufruft, indem du den synchronisierten Block verwendest, wie kann ich dann den Besitz auf den Thread übernehmen, der .notify aufrufen wird. Ich meine, der erste synchronisierte Block wurde wegen der Warte-Anweisung nicht beendet ... richtig? Wird es keinen gegenseitigen Ausschluss geben? –

1

Wie Dystroy sagte, müssen Sie eine Sperre für ein Objekt haben, um "warten" darauf zu nennen. Wenn aus irgendeinem Grund können Sie nicht oder wollen nicht tun, dass (wie das gleiche Verfahren läuft gleichzeitig versuchen, eine Sperre auf das gleiche Objekt zu erhalten), können Sie verwenden:

try{ 
    Thread.sleep(time); 
} catch (Exception ex){ 
    Thread.interrupted(); 
} 

Oder ein neues Objekt deklarieren auf dem eine Sperre erhalten werden soll.

2

Sie können wait (...) nicht in Servlet setzen, da doPost, doGet, ... keine synchronisierte Methode sind.

können Sie warten nur in synchronisierte Methode oder Block. So können Sie einen synchronisierten Block setzen und warten Sie darauf. Wie unten -

synchronized (object) { 
     try { 
      object.wait(1000*60); 
     } catch (Throwable ex) { 
      ex.printStackTrace(); 
     } 
    } 
2

Die angenommene Antwort fehlt eine Bedingung. Wann immer Sie warten, sollten Sie immer eine Bedingung überprüfen, um sich vor ungewolltem Aufwachen zu schützen. Im Grunde wird das Warten in allen Fällen, in denen es heißt, normalerweise wiederkehren. Es kann auch ohne ersichtlichen Grund zurückkehren. Sie sollten dem Muster von Javadoc folgen. Ich würde nicht empfehlen Throwable hier oder so ziemlich überall zu fangen. Fangen Sie stattdessen nur InterruptedException. Außerdem müssen Sie sicherstellen, dass die Bedingungsprüfung Thread-sicher ist. So zum Beispiel könnten Sie wie folgt vorgehen:

private boolean condition; 
private Object lock = new Object(); 
private long timeout = 1000; 

public void conditionSatisfied() { 
    synchronized (lock) { 
     condition = true; 
     lock.notify(); 
    } 
} 

public void awaitCondition() { 
    synchronized (lock) { 
     while (!condition) { 
      try { 
       lock.wait(timeout); 
      } catch (InterruptedException e) { 
       // Probably throw some application specific exception 
      } 
     } 
     // Perform action appropriate to condition 
    } 
} 

Sie werden feststellen, dass Sie in einer Schleife warten. Das Timeout bedeutet nur, dass Sie in Zeitabständen bis zum Timeout-Wert warten. Wenn Sie Ihre Wartezeit insgesamt begrenzen möchten, sollten Sie die aktuelle Zeit außerhalb der Schleife notieren und nach jeder Wartezeit überprüfen.

Verwandte Themen