web-dev-qa-db-ja.com

Javaスレッドの状態遷移、BLOCKEDへの待機、または実行可能?

SOコンセンサスとほぼすべてのJavaインターネット上のスレッド状態図、特にスレッド状態遷移に関してfromWAITINGnotify()またはnotifyAll()が呼び出された後...

  • WAITING never は直接RUNNABLEに移動します
  • スレッドは通知されるまで待機しています...その後、スレッドは になります ブロックされました...
  • このスレッドが通知されると、それは 実行できなくなります ...これはブロックされた状態です

したがって、SO=のコンセンサスは:notify()またはnotifyAll()を呼び出した後、スレッドがWAITINGからBLOCKEDに移行します下の図は、この遷移を緑色で示しています。

質問

なぜほとんどの ウェブ上の状態図 は、WAITINGではなくRUNNABLEからBLOCKEDへの遷移を示しているのですか?赤の説明は、誤った遷移を示しています。私は何かを逃していますか?

enter image description here

29
raffian

スレッドをWAITINGからRUNNABLEに移行するnotify呼び出しを示す図はすべて間違っています(または不明なショートカットを使用しています)。スレッドがnotifyから(または偽のウェイクアップからさえ)起こされると、待機しているオブジェクトのモニターを再度ロックする必要があります。これは BLOCKED 状態です。

モニターロックを待機してブロックされたスレッドのスレッド状態。ブロック状態のスレッドは、モニターロックが同期ブロック/メソッドに入るか、_Object.wait_を呼び出した後に同期ブロック/メソッドに再び入るのを待っています。

これは Object#notify() のjavadocで説明されています:

目覚めたスレッドは、現在のスレッドがこのオブジェクトのロックを放棄するまで続行できません。

および Object#wait()

スレッドは、モニターの所有権を再取得できるまで待機し、実行を再開します。

14

スレッドは[〜#〜] waiting [〜#〜]状態になります[〜#〜] block [〜#〜]状態になります。通知して[〜#〜] runnable [〜#〜]になります。

同じことが[〜#〜] timedwaiting [〜#〜]にも当てはまります。モニターは[〜#〜] block [〜#〜]状態になります。指定された時間が経過しても、他のいくつかのスレッド。(ダイアグラムを修正する必要があります)

1
user4768611

私は最近問題に焦点を合わせています。

oracleドキュメント Thread.State によると、LockSupport.park()を使用して現在のスレッドを「WAITING」または「TIMED_WAITING」状態にすることができます。

したがって、 LockSupport.unpark() を試行すると、指定されたスレッドは「WAITING」/「TIMED_WAITING」から「RUNNABLE」に戻ります。 (「BLOCKED」状態になるかどうかはわかりません)

0
hgfeaon