2012-06-08 107 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 
    } 
} 

您會注意到您正在等待一個循環。超時只是意味着您等待超時值的間隔。如果您希望對您的等待時間進行總體限制,則應該注意循環外的當前時間,並在每次等待後進行檢查。

相關問題