2012-06-08 42 views
6

Tôi đang chạy một ứng dụng web trong máy chủ ứng dụng Jboss và tôi đang cố triển khai phản hồi cơ sở sự kiện từ máy chủ.wait() trên Servlet ném ngoại lệ

Để thực hiện điều đó tôi đang sử dụng .wait() và .notify() trên lớp servlet. Về cơ bản có một yêu cầu Ajax, servlet chặn với wait cho đến khi có sự kiện trên máy chủ và nếu như vậy notify được kích hoạt trên servlet.

Vấn đề là khi tôi chờ đợi (1000 * 60) trên Servlet tôi nhận được:

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

Là nó thậm chí có thể làm một chờ đợi() trên một HttpServlet lớp học?

Trả lời

7

Trước khi bạn chờ một đối tượng, bạn phải sở hữu.

Việc này thường được thực hiện với câu lệnh được đồng bộ hóa.

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

và tôi phải làm như vậy trước khi thông báo? –

+0

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

+0

có somehting tôi không nhận được ... nếu tôi lấy quyền sở hữu với chủ đề gọi .wait bằng cách sử dụng khối được đồng bộ hóa làm thế nào tôi có thể lấy quyền sở hữu trên chuỗi sẽ gọi. Tôi có nghĩa là khối đồng bộ đầu tiên đã không hoàn thành do tuyên bố chờ đợi ... chính xác? Sẽ không có loại trừ lẫn nhau? –

1

Như Dystroy đã nói, bạn cần phải khóa trên vật để gọi "chờ" trên đó. Nếu vì một lý do nào, bạn không thể hoặc không muốn làm điều đó (ví dụ như cùng một phương pháp chạy đồng thời cố gắng để có được một khóa trên cùng một đối tượng), bạn có thể sử dụng:

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

Hoặc khai báo một đối tượng mới để lấy khóa.

2

Bạn không thể đặt chờ (...) trong servlet vì doPost, doGet, ... không được đồng bộ hóa phương pháp.

bạn có thể đặt chỉ chờ trong phương thức hoặc khối được đồng bộ hóa. Vì vậy, bạn có thể đặt một khối được đồng bộ hóa và đợi trong đó.Giống như bên dưới -

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

Câu trả lời được chấp nhận bị thiếu điều kiện. Bất cứ khi nào bạn chờ đợi, bạn nên luôn luôn kiểm tra một điều kiện để bảo vệ mình khỏi bị đánh thức giả mạo. Về cơ bản, chờ đợi được đảm bảo để trở lại bình thường trong tất cả các trường hợp nó nói nó sẽ. Nó cũng có thể trở lại không có lý do rõ ràng. Bạn nên theo mẫu từ Javadoc. Tôi sẽ không khuyên bạn nên bắt Throwable ở đây hoặc khá nhiều ở bất cứ đâu. Thay vào đó, chỉ bắt được InterruptedException. Ngoài ra, bạn cần đảm bảo rằng kiểm tra tình trạng là an toàn chỉ. Vì vậy, ví dụ: bạn có thể làm như sau:

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

Bạn sẽ nhận thấy rằng bạn đang đợi trong một vòng lặp. Thời gian chờ chỉ có nghĩa là bạn chờ trong khoảng thời gian lên đến giá trị hết thời gian chờ. Nếu bạn muốn đặt một giới hạn tổng thể về thời gian chờ đợi của bạn, bạn nên lưu ý thời gian hiện tại bên ngoài vòng lặp và kiểm tra nó sau mỗi lần chờ.

Các vấn đề liên quan