2010-08-03 14 views
19

Có tuyên bố chờ đợi này:Làm cách nào để phân biệt thời gian chờ (hết thời gian chờ) để thông báo hoặc hết thời gian chờ?

public final native void wait(long timeout) throws InterruptedException; 

Nó có thể thoát bởi InterruptedException, hoặc bằng thời gian chờ, hoặc vì Thông báo/notifyAll phương pháp được gọi là trong chủ đề khác, ngoại lệ là dễ dàng để bắt nhưng ...

Có cách nào để biết nguyên nhân thoát là hết thời gian hoặc thông báo?

EDIT:

Đây là một cách khéo léo có thể làm việc, (mặc dù tôi không thích nó)

  long tBefore=System.currentTimeMillis(); 
      wait(TIMEOUT); 
      if ((System.currentTimeMillis() - tBefore) > TIMEOUT) 
      { 
       //timeout 
      } 
+2

Tôi có nhu cầu tương tự và trong trường hợp của mình, hóa ra là một 'Semaphore' phù hợp hơn; 'Semaphore.tryAcquire (thời gian chờ lâu, đơn vị TimeUnit)' trả về 'false' nếu hết thời gian chờ. – Santosh

+0

Semaphore sẽ hoạt động trừ khi bạn cần có khả năng chờ đợi, không được hỗ trợ bởi hợp đồng công khai Semaphore. –

Trả lời

7

Bạn không thể phân biệt giữa hai trừ khi bạn cung cấp một số thêm mã. Ví dụ bằng cách thêm một ThreadLocalBoolean được thiết lập để true chỉ trên notify()

Nhưng trước tiên bạn phải chắc chắn logic của bạn đòi hỏi phải có sự khác biệt này.

+4

OP đã biết một ngoại lệ sẽ không bị ném và muốn phân biệt giữa thời gian chờ và thông báo. Điều này không cung cấp bất kỳ thông tin hữu ích nào cho mục đích đó. –

+1

cảm ơn, tôi hiểu lầm OP. Đã cập nhật ngay bây giờ. – Bozho

+0

+1 để viết lại, và có một boolean một phương pháp đồng bộ là những gì tôi đang sử dụng bây giờ –

1

Ngoại lệ không được ném vào thông báo và hết giờ.

Tôi nghĩ tốt hơn nên dựa vào các đối tượng đồng bộ hóa gói java.lang.concurrent thay vì sử dụng Object.wait().

12

Điều này không trả lời chính xác câu hỏi, nhưng điều này có thể giải quyết được vấn đề của bạn: Sử dụng các cơ chế đồng thời cấp cao hơn. Chờ/thông báo thường thấp hơn mức bạn muốn, vì lý do này trong số nhiều người khác.

Ví dụ: nếu bạn đang sử dụng BlockingQueue.poll(long, TimeUnit), bạn có thể kiểm tra xem kết quả có là không biết liệu bạn đã hết thời gian chưa.

16

Có một lý do nữa để thông báo có thể trả về: báo thức giả mạo. Đây là một điều không thể nhưng có thể xảy ra, bởi vì ngăn ngừa việc đánh thức giả mạo rất tốn kém trên một số kết hợp phần cứng/hệ điều hành.

Vì lý do này, bạn luôn phải gọi wait() trong vòng lặp và kiểm tra lại điều kiện mà bạn đang đợi. Trong quá trình này, thật dễ dàng để kiểm tra thời gian chờ cùng một lúc.

Để biết chi tiết, tôi đề xuất sách "Java Concurrency In Practice". Và sử dụng các cấu trúc mức cao hơn để có được điều này chính xác cho bạn.

+0

+1 Tôi sẽ có trong tài khoản những thức tỉnh giả –

2

Không có cách nào để nói trực tiếp - tức là, bạn sẽ phải thêm mã bổ sung để xác định điều này. Thường thì khi bạn đợi(), bạn đang chờ đợi một điều gì đó xảy ra làm thay đổi trạng thái của một đối tượng theo một cách nào đó - ví dụ: bằng cách thiết lập một biến boolean, có lẽ. Nếu trường hợp đó xảy ra, thì bạn có thể chỉ cần kiểm tra trạng thái của biến đó để xem sự kiện đã xảy ra hay bạn chỉ hết thời gian chờ. Hoặc bạn có thể xem xét giá trị của System.currentTimeMillis() để xem thời gian trôi qua lớn hơn hoặc bằng khoảng thời gian chờ - nếu có, đó sẽ là đầu mối bạn có thể đã hết thời gian chờ (mặc dù nó không phải là sự đảm bảo tuyệt đối). Hoặc nếu thời gian trôi qua nhỏ hơn khoảng thời gian chờ thì bạn chắc chắn đã không hết giờ. cái đó có giúp ích không?

+0

Tôi thực sự sử dụng currentTimeMillis(), nhưng tôi đã tự hỏi nếu có một số cách tốt hơn –

+0

@ Hernán Eche Như tôi đã đưa vào câu trả lời của tôi không phải là một đảm bảo tuyệt đối. nếu bạn có thể cho biết, tại sao bạn muốn xác định xem nó đã hết thời gian chưa? Chúng ta có thể tìm một số giải pháp. – YoK

+0

vâng, tôi biết đó không phải là một cách tiếp cận rất tốt, tôi sử dụng nó cho một vòng lặp trong khi (true) {wait (timeout); các nhiệm vụ khác..; } vì vậy nó có thể thoát khỏi vòng lặp khi chờ đợi đã thực sự được thông báo, ví dụ nếu chờ đợi sẽ trả về boolean, nó sẽ là một cái gì đó giống như while (true) {if (wait (timeout)) break; các nhiệm vụ khác..; } anyway tôi sẽ đóng gói nó tất cả trong một lớp học và một lá cờ với phương pháp đồng bộ để chờ đợi/thông báo song song với các thiết lập của lá cờ này –

3

Không sử dụng System.currentTimeMillis(), sử dụng System.nanoTime() để thay thế.

Lần đầu tiên đo thời gian tuyệt đối (dựa trên đồng hồ hệ thống) và có thể có kết quả tò mò nếu thời gian hệ thống bị thay đổi. Ví dụ: Thời gian chờ 5 giây có thể có thời lượng một giờ nếu đồng hồ được di chuyển lùi một giờ hoặc chờ 10 phút sẽ được thực hiện sau 0 giây nếu đồng hồ được di chuyển trước.

Loại thứ hai đo thời gian tương đối. Nó sẽ luôn luôn chạy theo một hướng ở tốc độ không đổi, nhưng nó không có nguồn gốc. Điều đó có nghĩa rằng các giá trị chỉ có thể được sử dụng để đo thời gian tương đối, nhưng có thể và không nên được sử dụng để xác định một ngày.