6

我正在 Jboss 应用程序服务器中运行一个 Web 应用程序,并且我正在尝试从服务器实现一个基于事件的响应。

为了实现这一点,我在 servlets 类上使用了 .wait() 和 .notify() 。基本上有一个 Ajax 请求,servlet 阻塞,wait直到服务器上有一个事件,如果有,notify则在 servlet 上触发。

问题是当我在 Servlet 上等待(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

您不能将 wait(...) 放在 servlet 中,因为 doPost、doGet、... 不是同步方法。

您只能在同步方法或块中放置等待。因此,您可以放置​​一个同步块并在其中放置等待。如下所示 -

    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 回答