2010-08-03 63 views
19

有了這個等待聲明:如何區分等待(超時超時)退出通知或超時?

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

它可以通過InterruptedException的退出,或超時,或因爲通知/ notifyAll的方法被調用在另一個線程,異常是容易趕上,但...

有有什麼方法可以知道退出原因是超時還是通知?

編輯:

這是一個可以工作,(雖然我不喜歡它),除非你提供一些額外的你無法區分這兩種一個取巧的辦法

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

我也有類似的需求,並在我的情況下,它變成了一個'Semaphore'更適合; 'Semaphore.tryAcquire(long timeout,TimeUnit unit)'如果超時已過,則返回'false'。 – Santosh 2017-06-24 10:52:00

+0

信號燈會工作,除非你需要有等待其不被信號量公共合同支持的能力。 – 2017-12-22 05:33:25

回答

7

碼。例如通過增加ThreadLocalBoolean被設置爲truenotify()

但首先你必須確保你的邏輯需要這種分化。

+4

OP已經知道一個異常不會被拋出,並希望區分超時和通知。這沒有提供任何有用的信息,爲此。 – 2010-08-03 15:04:14

+1

謝謝,我誤解了OP。現在更新。 – Bozho 2010-08-03 19:19:56

+0

+1用於重寫,並且是布爾值同步方法是我現在使用的方法 – 2010-08-04 11:21:04

1

異常不會引發通知和超時。

我認爲最好依靠java.lang.concurrent包同步對象而不是使用Object.wait()

12

這並不完全回答問題,但它可能會解決您的問題:使用更高級別的併發機制。由於這個原因,等待/通知通常比你想要的更低級別。

例如,如果您使用的是BlockingQueue.poll(long, TimeUnit),則可以檢查結果是否爲空以知道您是否超時。

16

還有一個原因是通知可以返回:虛假喚醒。這是不太可能的,但可能的事情,因爲防止虛假喚醒在某些硬件/操作系統組合上非常昂貴。

因此,您總是必須在循環中調用wait()並重新檢查您正在等待的條件。在這項工作中,很容易同時檢查超時。

有關詳細信息,我推薦「Java併發實踐」一書。並使用更高層次的結構,這將使你的這一切都正確。

+0

+1我會在帳戶那些虛假喚醒 – 2010-08-03 15:46:23

2

無法直接告知 - 也就是說,您必須添加額外的代碼才能確定這一點。通常當你等待()時,你正在等待某些事情發生,以某種方式改變對象的狀態 - 例如,通過設置一個布爾變量,也許。如果是這種情況,那麼您可能只需檢查該變量的狀態以查看事件是否發生,或者您只是超時。或者你可以看看System.currentTimeMillis()的值來查看經過時間是否大於或等於超時時間 - 如果是,那可能是你可能已超時的線索(儘管這不是絕對的保證)。或者如果經過的時間少於超時時間,那麼你肯定沒有超時。這有幫助嗎?

+0

我實際上使用currentTimeMillis(),但我想知道是否有一些更好的方法 – 2010-08-03 15:26:37

+0

@HernánEche因爲我已經把我的答案並不絕對保證。如果你可以告訴,爲什麼你要確定它是否超時?我們可以尋找一些解決方案。 – YoK 2010-08-03 15:32:48

+0

是的,我知道這不是一個很好的方法,我用它作爲循環while(true){wait(timeout);其他任務..; }所以它可以退出循環,當等待真正得到通知,例如,如果等待將返回布爾值,它會像while(true){if(wait(timeout))break;其他任務..; }無論如何,我將它封裝在一個類和一個標誌與同步方法等待/通知與此標誌的設置並行 – 2010-08-03 15:59:59

3

請勿使用System.currentTimeMillis(),請使用System.nanoTime()代替。

第一個meassures絕對時間(根據系統時鐘),如果系統時間更改可能會好奇的結果。例如:如果該時鐘由一個小時向後移動,或有10分鐘的等待將0秒後,如果時鐘移動foreward進行5秒的等待可以有一個小時的持續時間。

第二個meassures相對時間。它總是以恆定的速度在一個方向運行,但它沒有起源。這意味着這些值只能用於確定相對時間,但可以並不應該用於確定日期。