2012-06-08 4 views
6

Я запускаю веб-приложение на сервере приложений Jboss, и я пытаюсь реализовать ответ базы событий с сервера.wait() on Servlet throws Exception

Для этого я использую .wait() и .notify() в классе сервлетов. В основном есть запрос Ajax, блоки сервлетов с wait до тех пор, пока на сервере не появится событие, и еслиуволен с сервлетом.

Проблема заключается в том, когда я ждать (1000 * 60) на Servlet я получаю:

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

Возможно ли это сделать ожидание() в классе 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

есть что-то, что я не получаю ... если я возьмите владение с потоком, который вызывает .wait, используя синхронизированный блок, как я могу взять собственность на поток, который будет вызывать .notify. Я имею в виду, что первый синхронизированный блок не завершился из-за оператора ожидания ... правильно? Разве не будет взаимного исключения? –

1

Как сказал Dystroy, вам нужно иметь блокировку объекта, чтобы называть его «wait». Если по какой-то причине, вы не можете или не хотите, чтобы сделать это (например, тот же метод работает одновременно пытается получить блокировку на тот же объект), вы можете использовать:

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

Или объявить новый объект на котором можно получить замок.

2

Вы не можете поместить wait (...) в сервлет, потому что doPost, doGet, ... не синхронизированный метод.

вы можете поместить wait только синхронизированным способом или блоком. Таким образом, вы можете поместить синхронизированный блок и поместить в него wait.Like ниже -

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 
    } 
} 

Вы заметите, что вы ждете в цикле. Тайм-аут просто означает, что вы будете ждать с интервалом до значения таймаута. Если вы хотите установить общий предел времени ожидания, вы должны отметить текущее время вне цикла и проверить его после каждого ожидания.