2012-05-01 40 views
5

Không phải là có thể thông báo() trong một luồng khác được gọi trước khi chờ() trong một chuỗi? Nó đang xảy ra với tôi.Java thông báo() được gọi trước khi chờ()

Máy khách yêu cầu giá trị từ mục tiêu và chờ trên biến kết quả RV. Trong trường hợp mục tiêu là chính máy khách, tôi cập nhật RV với kết quả chính xác và gọi thông báo() trên RV trong một chuỗi khác.

class EMU { 

    ResultVar RV; 
    Address my_address; 

    ResultVar findValue(String key) { 
    String tgt = findTarget(key); 
    sendRequest(tgt, key); 
    synchronized(RV) { 
     RV.wait(); 
    } 

    return RV; 
    } 

    Runnable Server = new Runnable() { 
    public void run() { 
     //code to receive connections. Assume object of type Request is read from the stream. 
     Request r = (Request) ois.readObject(); 
     if(r.requesterAddr.compareTo(my_address) == 0) { 
     String val = findVal(key); 
     RV.putVal(val); 
     synchronized(RV){ 
      RV.notify(); 
     } 
     } 
    } 
    }; 
} 

Vấn đề là trước khi người yêu cầu hoàn thành tất cả "mạng" (gửi chính xác trong ví dụ trên), kết quả được cập nhật trong biến kết quả. Khi chuỗi yêu cầu bây giờ gọi wait(), chương trình không tiếp tục, vì thông báo đã được gọi.

Làm cách nào để ngăn chặn?

+1

'Trong trường hợp mục tiêu là khách hàng itself' Ý anh là gì đây? Bạn có thể đặt một số mẫu mã? – Cratylus

+1

@shishir garg bạn có thể vui lòng dán một số mã –

+0

Nếu không thấy mã khó trả lời - 2 bình luận mặc dù: a) nói chung là tốt hơn để sử dụng notifyAll thay vì thông báo, trừ khi bạn biết bạn đang làm gì b) thông báo có thể dễ bị lỗi và bạn nên sử dụng API đồng thời cấp cao hơn trừ khi bạn cần một cái gì đó rất cụ thể. – assylias

Trả lời

4

Không có gì ngăn bạn gọi notify trên một đối tượng mà không phải là wait ed bởi thread khác.

Nghe có vẻ như những gì bạn muốn là chờ đợi chỉ khi một số điều kiện được giữ. Ví dụ:

synchronized (results) { 
    while (!results.hasResults()) { 
     // no results yet; wait for them 
     try { 
      results.wait(); 
     } catch (InterruptedException ie) { /* ignore */ } 
    } 
} 
1

Tôi thật sự khuyên bạn không nên phát minh lại bánh xe.

Giao diện Future của Java được thiết kế cho các kết quả chỉ có thể đến sau và lớp FutureTask triển khai giao diện này.

Để chuỗi đầu tiên có quyền truy cập vào Tương lai và tải chuỗi thứ hai để chạy FutureTask và tất cả nội dung này sẽ được xử lý cho bạn. Bạn cũng nhận được hỗ trợ timeout miễn phí.

0

Sử dụng một số điều kiện trước khi đi chờ đợi() và chắc chắn rằng điều kiện là chủ đề an toàn :)

class EMU{ 
    ResultVar RV; 
    Address my_address; 
    volatile boolean condition = true; 

    ResultVar findValue(String key){ 
     String tgt = findTarget(key); 
     sendRequest(tgt, key); 
     synchronized(RV){ 
      while(condition == true) 
      { 
       RV.wait(); 
      } 
     } 
     return RV; 
    } 

    Runnable Server = new Runnable(){ 
     public void run(){ 
      //code to receive connections. Assume object of type Request is read from the stream. 
      Request r = (Request) ois.readObject(); 
      if(r.requesterAddr.compareTo(my_address) == 0){ 
       String val = findVal(key); 
       RV.putVal(val); 
       synchronized(RV){ 
        condition = false; 
        RV.notify(); 
       } 
      } 
     } 

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