スレッド状態WAITとスレッド状態BLOCKEDの違いは何ですか?
ブロック
モニターロックを待機してブロックされているスレッドは、この状態です。待機中
別のスレッドが特定のアクションを実行するのを無期限に待機しているスレッドは、この状態です。
違いを私に説明しません。
スレッド状態WAITとスレッド状態BLOCKEDの違いは何ですか?
ブロック
モニターロックを待機してブロックされているスレッドは、この状態です。待機中
別のスレッドが特定のアクションを実行するのを無期限に待機しているスレッドは、この状態です。
違いを私に説明しません。
回答:
スレッドはwait()
、オブジェクトを呼び出すと待機状態になります。これは待機状態と呼ばれます。スレッドが待機状態に達すると、他のスレッドが呼び出されるまで、notify()
またはnotifyAll()
オブジェクト上で待機する必要があります。
このスレッドが通知されると、実行できなくなります。他のスレッドにも通知される(を使用notifyAll()
)か、最初のスレッドが作業を完了していない可能性があります。そのため、機会が得られるまでブロックされます。これはブロック状態と呼ばれます。ブロック状態は、スレッドがオブジェクトのロックを取得しようとし、他のスレッドがすでにロックを保持している場合に発生します。
他のスレッドが終了し、このスレッドが発生する可能性があると、そのスレッドはRunnable状態に移行します。その後、JVMスレッドメカニズムに基づいて作業を取得し、実行状態に移行します。
違いは比較的単純です。
このBLOCKED
状態では、スレッドはsynchronized
ブロックに入りますがsynchronized
、同じオブジェクトのブロック内で現在実行中の別のスレッドがあります。最初のスレッドは、2番目のスレッドがそのブロックを終了するのを待つ必要があります。
このWAITING
状態では、スレッドは別のスレッドからのシグナルを待っています。これは通常Object.wait()
、またはを呼び出すことで発生しThread.join()
ます。スレッドはObject.notify()
、別のスレッドがを呼び出すか、終了するまで、この状態のままになります。
Object.wait()
直接使用することはめったにありませんが、WAITING
ロック、ブロッキングキューなど、より高レベルの同時実行構造も使用する状態になります。
RUNNING
状態にあります。
Thread.State
は、「...これらの状態は仮想マシンの状態であり、オペレーティングシステムのスレッドの状態を反映していません。」つまり、JVMは、Javaコードを実行しているスレッド、システムコールが戻るのを待機しているスレッド、またはタイムスライスを待機しているスレッドの違いを気にしません。これらはすべてRUNNABLE
、JVMに関する限りです。
WAITING
状態から移動するとき、BLOCKED
待機していたオブジェクトに関連付けられたロックを取得できるようになるまで、スレッドはまずその状態に移行する必要があることを付け加えるとよいでしょう。
ブロック状態と待機状態の重要な違いは、スケジューラへの影響です。ブロックされた状態のスレッドがロックを求めて競合しています。そのスレッドは依然としてスケジューラがサービスする必要があるものとして数えられ、実行中のスレッドに与える時間に関するスケジューラの決定に考慮される可能性があります(それにより、ロックでブロックされているスレッドにチャンスを与えることができます)。
スレッドが待機状態になると、スレッドがシステムに与えるストレスは最小限に抑えられ、スケジューラーはそれを心配する必要がなくなります。通知を受け取るまで休止状態になります。OSスレッドを占有し続けるという事実を除いて、それは完全に機能しません。
これが、notifyAllの使用が理想的とは言えない理由です。これにより、システムに負荷をかけずに以前は無意味に休止していた一連のスレッドが起動し、ほとんどのスレッドがロックを取得するまでブロックし、条件を見つけます。待つことは本当ではなく、待つことに戻ります。進行する可能性のあるスレッドのみに通知することをお勧めします。
(組み込みロックの代わりにReentrantLockを使用すると、1つのロックに対して複数の条件を設定できるため、通知されたスレッドが特定の条件で待機しているスレッドであることを確認でき、スレッドが通知を受けた場合の通知喪失のバグを回避できます動作できないもの。)
スレッドダンプを解釈するための簡略化された視点:
RUNNABLE
は全く正しくありません。Java実行キューにあるが実行されていないか、Javaコードを実行している可能性があります。それは原産国を呼び出す必要はありません。
この例を見てください:
スレッド状態のデモンストレーション。
/*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();
}
}
}
}