6

Jboss アプリケーション サーバーで Web アプリを実行しており、サーバーからのイベント ベース応答を実装しようとしています。

それを達成するために、サーブレット クラスで .wait() と .notify() を使用しています。基本的にAjaxリクエストがありwait、サーバーにイベントが発生するまでサーブレットはブロックされ、イベントが発生した場合notifyはサーブレットで起動されます。

問題は、取得したサーブレットで待機 (1000*60) する場合です。

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

HttpServlet クラスで wait() を実行することさえ可能ですか?

4

4 に答える 4

7

オブジェクトを待機する前に、所有権を取得する必要があります。

これは通常、同期ステートメントで行われます。

    synchronized (obj) {
        try {
            obj.wait(someTime);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
于 2012-06-08T18:12:07.067 に答える
2

doPost、doGet、... は同期メソッドではないため、wait(...) をサーブレットに入れることはできません。

同期されたメソッドまたはブロックでのみ待機できます。したがって、同期ブロックを配置して、その中に待機を配置できます。以下のように -

    synchronized (object) {
        try {
            object.wait(1000*60);
        } catch (Throwable ex) {
            ex.printStackTrace();
        }
    }
于 2012-06-08T18:19:19.873 に答える
2

受け入れられた回答には条件がありません。待機するときはいつでも、偽のウェイクアップから身を守るために、常に状態を確認する必要があります。基本的に、wait は、すべての場合に正常に戻ることが保証されています。また、明らかな理由もなく戻ることもあります。Javadocのパターンに従う必要があります。ここで、またはほとんどどこでも Throwable をキャッチすることはお勧めしません。代わりに、InterruptedException だけをキャッチします。また、条件チェックがスレッドセーフであることを確認する必要があります。したがって、たとえば、次のことができます。

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
    }
}

ループで待機していることに気付くでしょう。タイムアウトは、タイムアウト値までの間隔で待機することを意味します。待機時間に全体的な制限を設けたい場合は、ループ外の現在の時間を記録し、各待機後に確認する必要があります。

于 2012-06-08T22:12:22.893 に答える
1

Dystroy が言ったように、「待機」を呼び出すにはオブジェクトをロックする必要があります。何らかの理由でそれを行うことができない、または行いたくない場合 (同じメソッドを同時に実行して同じオブジェクトのロックを取得しようとするなど) は、次を使用できます。

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

または、ロックを取得する新しいオブジェクトを宣言します。

于 2012-06-08T18:17:42.817 に答える