web-dev-qa-db-ja.com

WAITスレッド状態とBLOCKEDスレッド状態の違い

スレッド状態WAITとスレッド状態BLOCKEDの違いは何ですか?

Thread.Stateドキュメント

ブロック済み
モニターロックを待機してブロックされているスレッドは、この状態です。

待機中
別のスレッドが特定のアクションを実行するのを無期限に待機しているスレッドは、この状態です

私に違いを説明しません。

84
More Than Five

スレッドは、オブジェクトでwait()を呼び出すと待機状態になります。これはWaiting Stateと呼ばれます。スレッドが待機状態に達すると、他のスレッドがオブジェクトでnotify()またはnotifyAll()を呼び出すまで待機する必要があります。

このスレッドが通知されると、実行できなくなります。他のスレッドにも通知される(notifyAll()を使用)か、最初のスレッドが作業を終了していないため、チャンスが来るまでブロックされている可能性があります。これはBlocked Stateと呼ばれます。スレッドがオブジェクトのロックを取得しようとし、他のスレッドがすでにロックを保持している場合は常に、ブロック状態が発生します。

他のスレッドが去り、このスレッドがチャンスになると、Runnable状態に移行します。その後、JVMスレッドメカニズムに基づいて作業をピックアップし、実行状態に移行します。

64
Ankit Bansal

違いは比較的単純です。

BLOCKED状態では、スレッドはsynchronizedブロックに入ろうとしていますが、同じオブジェクトのsynchronizedブロック内で現在実行中の別のスレッドがあります。その後、最初のスレッドは、2番目のスレッドがそのブロックを終了するまで待機する必要があります。

WAITING状態では、スレッドは別のスレッドからのシグナルを待っています。これは通常、Object.wait()またはThread.join()を呼び出すことで発生します。スレッドは、別のスレッドがObject.notify()を呼び出すか、または終了するまで、この状態のままになります。

77
Flavio

ブロック状態と待機状態の重要な違いは、スケジューラーへの影響です。ブロックされた状態のスレッドは、ロックを競合するwaitsetの一部です。そのスレッドは、スケジューラが処理する必要があるものとしてカウントされ、実行中のスレッドに与える時間に関するスケジューラの決定に考慮される可能性があります。

スレッドが待機状態になると、スレッドがシステムに与えるストレスは最小限に抑えられ、スケジューラーはそれを心配する必要がなくなります。通知を受信するまで休止状態になります。 OSスレッドを占有したままにするという事実を除いて、完全に機能しません。

これがnotifyAllの使用が理想的とは言えない理由です。これにより、以前はシステムに負荷をかけずに休眠していたスレッドの束が起こされ、ロックの取得が可能になるまでブロックされます。待つことは真実ではありません。進行する可能性のあるスレッドのみに通知することをお勧めします。

(組み込みロックの代わりにReentrantLockを使用すると、1つのロックに複数の条件を設定できるため、通知されたスレッドが特定の条件で待機していることを確認でき、スレッドが通知を受けた場合の紛失通知バグを回避できます行動できないもの)

16
Nathan Hughes

スレッドダンプを解釈するための簡略化されたパースペクティブ:

  • WAIT-仕事が与えられるのを待っているので、今はアイドル状態です。
  • ブロック-仕事を終わらせるのに忙しいが、別のスレッドが邪魔をしているので、今はアイドル状態です。
  • RUNNABLE ...(ネイティブメソッド)-JVMに関しては、実行可能なネイティブコード(まだ終了していない)を実行するようにコールアウトしました。それ以上の情報を提供しません。一般的な例としては、Cでコーディングされたネイティブソケットリスナーメソッドがあります。これは、実際にトラフィックの到着を待機しているため、現在はアイドル状態です。この状況では、これは特別な種類のWAITと見なすことができます。実際にはまったく実行されていない(CPUの焼き付きはありません)が、JavaではなくOSスレッドダンプを使用する必要があるからです。スレッドダンプを参照してください。
12
oldguy

Blocked-スレッドはスレッドライフサイクルの実行可能な状態にあり、オブジェクトロックを取得しようとしています。待機-スレッドはスレッドライフサイクルの待機状態にあり、通知信号がスレッドの実行可能な状態になるのを待機しています。

1
Prakash Bisht

この例を参照してください:

スレッド状態のデモ。

/*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();
        }
    }
}
}
0
murali