40

この待機宣言を持つ:

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

InterruptedException、またはタイムアウトによって終了する可能性があります。または、別のスレッドで Notify/NotifyAll メソッドが呼び出されたため、例外をキャッチするのは簡単ですが...

終了の原因がタイムアウトか通知かを知る方法はありますか?

編集:

これはうまくいくかもしれないトリッキーな方法です(私は好きではありませんが)

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

7 に答える 7

18

通知が返される理由がもう1つあります。それは、偽のウェイクアップです。一部のハードウェア/OSの組み合わせでは、誤ったウェイクアップを防止するのに非常に費用がかかるため、これはありそうもないが可能性のあることです。

このため、常にループでwait()を呼び出し、待機している条件を再確認する必要があります。この作業中に、同時にタイムアウトを確認するのは簡単です。

詳細については、「JavaConcurrencyInPractice」という本をお勧めします。そして、これをすべて正しくする高レベルの構成を使用します。

于 2010-08-03T15:11:14.743 に答える
14

追加のコードを提供しない限り、2 つを区別することはできません。たとえば、on のみにThreadLocal Boolean設定されている a を追加することによってtruenotify()

ただし、最初に、ロジックでこの区別が必要であることを確認する必要があります。

于 2010-08-03T14:58:41.803 に答える
14

これは質問に正確に答えるものではありませんが、おそらく問題を解決するでしょう: より高いレベルの同時実行メカニズムを使用してください。通常、待機/通知は、他の多くの理由の中でこの理由により、必要以上に低レベルです。

たとえば、 を使用してBlockingQueue.poll(long, TimeUnit)いる場合、結果が null かどうかをチェックして、タイムアウトしたかどうかを知ることができます。

于 2010-08-03T15:01:03.560 に答える
7

を使用せずSystem.currentTimeMillis()System.nanoTime()代わりに使用してください。

最初のものは (システム クロックに基づいて) 絶対時間を測定し、システム時間が変更されると奇妙な結果になる可能性があります。たとえば、時計を 1 時間戻すと 5 秒の待機は 1 時間になり、時計を進めると 0 秒後に 10 分間の待機が行われます。

2 つ目は相対時間を測定します。常に一定の速度で一方向に走りますが、原点はありません。つまり、値は相対時間を測定するためにのみ使用できますが、日付を決定するために使用することはできませんし、使用すべきではありません。

于 2014-12-16T14:05:10.340 に答える
2

直接伝える方法はありません。つまり、これを判断するにはコードを追加する必要があります。多くの場合、wait()を実行すると、オブジェクトの状態を何らかの方法で変更する何かが発生するのを待っています。たとえば、ブール変数を設定するなどです。その場合は、その変数の状態をチェックして、イベントが発生したかどうか、または単にタイムアウトしたかどうかを確認できる場合があります。または、System.currentTimeMillis()の値を調べて、経過時間がタイムアウト期間以上であることを確認できます。そうである場合は、おそらくタイムアウトした手がかりになります(絶対的な保証ではありませんが) )。または、経過時間がタイムアウト期間よりも短い場合は、確実にタイムアウトしていません。それは役に立ちますか?

于 2010-08-03T15:22:33.110 に答える
1

通知およびタイムアウト時に例外はスローされません。

java.lang.concurrentを使用する代わりに、パッケージ同期オブジェクトに依存する方がよいと思いますObject.wait()

于 2010-08-03T14:59:07.513 に答える