2012-06-08 77 views
6

我运行JBoss应用服务器的一个Web应用程序,我想实现从服务器的事件基准响应。等待()上的Servlet抛出异常

为了实现这个目标,我使用.wait()和.notify()上的servlet类。基本上有一个Ajax请求,servlet在wait之前被阻塞,直到服务器上发生事件,如果是,则在该servlet上触发notify

问题是,当我做了Servlet我得到等待(1000 * 60):

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

它甚至有可能做一个wait()在HttpServlet类?

回答

7

在等待对象之前,您必须取得所有权。

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

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

我必须在通知之前做同样的事情吗? –

+0

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

+0

有一些我不明白如果我通过使用synchronized块取得调用.wait的线程的所有权后,我如何才能取得将调用.notify的线程的所有权。我的意思是第一个同步块没有完成,因为等待声明...正确?不会互相排斥吗? –

1

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

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

或宣布一个新的对象在哪获得锁定。

2

你不能把等待(...)中的servlet,因为doPost方法,的doGet,...不同步的方法。

你可以把等待只在同步的方法或块。所以你可以把一个同步的块,并把它等待。如下 -

synchronized (object) { 
     try { 
      object.wait(1000*60); 
     } catch (Throwable ex) { 
      ex.printStackTrace(); 
     } 
    } 
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 
    } 
} 

您会注意到您正在等待一个循环。超时只是意味着您等待超时值的间隔。如果您希望对您的等待时间进行总体限制,则应该注意循环外的当前时间,并在每次等待后进行检查。

相关问题