我正在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()吗?
答案 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();
}
或者声明一个获取锁定的新对象。