スレッド状態WAITとスレッド状態BLOCKEDの違いは何ですか?
ブロック済み
モニターロックを待機してブロックされているスレッドは、この状態です。待機中
別のスレッドが特定のアクションを実行するのを無期限に待機しているスレッドは、この状態です
私に違いを説明しません。
スレッドは、オブジェクトでwait()
を呼び出すと待機状態になります。これはWaiting Stateと呼ばれます。スレッドが待機状態に達すると、他のスレッドがオブジェクトでnotify()
またはnotifyAll()
を呼び出すまで待機する必要があります。
このスレッドが通知されると、実行できなくなります。他のスレッドにも通知される(notifyAll()
を使用)か、最初のスレッドが作業を終了していないため、チャンスが来るまでブロックされている可能性があります。これはBlocked Stateと呼ばれます。スレッドがオブジェクトのロックを取得しようとし、他のスレッドがすでにロックを保持している場合は常に、ブロック状態が発生します。
他のスレッドが去り、このスレッドがチャンスになると、Runnable状態に移行します。その後、JVMスレッドメカニズムに基づいて作業をピックアップし、実行状態に移行します。
違いは比較的単純です。
BLOCKED
状態では、スレッドはsynchronized
ブロックに入ろうとしていますが、同じオブジェクトのsynchronized
ブロック内で現在実行中の別のスレッドがあります。その後、最初のスレッドは、2番目のスレッドがそのブロックを終了するまで待機する必要があります。
WAITING
状態では、スレッドは別のスレッドからのシグナルを待っています。これは通常、Object.wait()
またはThread.join()
を呼び出すことで発生します。スレッドは、別のスレッドがObject.notify()
を呼び出すか、または終了するまで、この状態のままになります。
ブロック状態と待機状態の重要な違いは、スケジューラーへの影響です。ブロックされた状態のスレッドは、ロックを競合するwaitsetの一部です。そのスレッドは、スケジューラが処理する必要があるものとしてカウントされ、実行中のスレッドに与える時間に関するスケジューラの決定に考慮される可能性があります。
スレッドが待機状態になると、スレッドがシステムに与えるストレスは最小限に抑えられ、スケジューラーはそれを心配する必要がなくなります。通知を受信するまで休止状態になります。 OSスレッドを占有したままにするという事実を除いて、完全に機能しません。
これがnotifyAllの使用が理想的とは言えない理由です。これにより、以前はシステムに負荷をかけずに休眠していたスレッドの束が起こされ、ロックの取得が可能になるまでブロックされます。待つことは真実ではありません。進行する可能性のあるスレッドのみに通知することをお勧めします。
(組み込みロックの代わりにReentrantLockを使用すると、1つのロックに複数の条件を設定できるため、通知されたスレッドが特定の条件で待機していることを確認でき、スレッドが通知を受けた場合の紛失通知バグを回避できます行動できないもの)
スレッドダンプを解釈するための簡略化されたパースペクティブ:
Blocked-スレッドはスレッドライフサイクルの実行可能な状態にあり、オブジェクトロックを取得しようとしています。待機-スレッドはスレッドライフサイクルの待機状態にあり、通知信号がスレッドの実行可能な状態になるのを待機しています。
この例を参照してください:
スレッド状態のデモ。
/*NEW- thread object created, but not started.
RUNNABLE- thread is executing.
BLOCKED- waiting for monitor after calling wait() method.
WAITING- when wait() if called & waiting for notify() to be called.
Also when join() is called.
TIMED_WAITING- when below methods are called:
Thread.sleep
Object.wait with timeout
Thread.join with timeout
TERMINATED- thread returned from run() method.*/
public class ThreadBlockingState{
public static void main(String[] args) throws InterruptedException {
Object obj= new Object();
Object obj2 = new Object();
Thread3 t3 = new Thread3(obj,obj2);
Thread.sleep(1000);
System.out.println("nm:"+t3.getName()+",state:"+t3.getState().toString()+
",when Wait() is called & waiting for notify() to be called.");
Thread4 t4 = new Thread4(obj,obj2);
Thread.sleep(3000);
System.out.println("nm:"+t3.getName()+",state:"+t3.getState().toString()+",After calling Wait() & waiting for monitor of obj2.");
System.out.println("nm:"+t4.getName()+",state:"+t4.getState().toString()+",when sleep() is called.");
}
}
class Thread3 extends Thread{
Object obj,obj2;
int cnt;
Thread3(Object obj,Object obj2){
this.obj = obj;
this.obj2 = obj2;
this.start();
}
@Override
public void run() {
super.run();
synchronized (obj) {
try {
System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",Before Wait().");
obj.wait();
System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",After Wait().");
synchronized (obj2) {
cnt++;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Thread4 extends Thread{
Object obj,obj2;
Thread4(Object obj,Object obj2){
this.obj = obj;
this.obj2 = obj2;
this.start();
}
@Override
public void run() {
super.run();
synchronized (obj) {
System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",Before notify().");
obj.notify();
System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",After notify().");
}
synchronized (obj2) {
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}