Servlet上的wait()抛出异常

时间:2012-06-08 18:09:46

标签: java events servlets

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

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

问题是当我在Servlet上等待(1000 * 60)时:

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

甚至可以在HttpServlet类上执行wait()吗?

4 个答案:

答案 0 :(得分:7)

在等待某个对象之前,您必须拥有所有权。

这通常是使用同步语句完成的。

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

答案 1 :(得分:2)

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

你只能在同步方法或阻止中等待。所以你可以放一个同步块并放入等待。如下所示 -

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

答案 2 :(得分:2)

接受的答案是错过了一个条件。每当你等待时,你应该总是检查一个条件,以保护自己免受虚假的唤醒。基本上,等待保证在所说的所有情况下都会正常返回。它也可以没有明显的原因返回。您应该遵循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
    }
}

你会注意到你正在等待一个循环。超时仅表示您以超时值的间隔等待。如果你想对你的等待时间进行总体限制,你应该记下循环之外的当前时间,并在每次等待后检查它。

答案 3 :(得分:1)

正如Dystroy所说,你需要锁定一个对象来对其进行“等待”。如果由于某种原因,您不能或不想这样做(例如同时运行同一个方法试图锁定同一个对象),您可以使用:

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

或者声明一个获取锁定的新对象。