[java] WAIT 및 BLOCKED 스레드 상태의 차이점

스레드 상태 WAIT와 스레드 상태 BLOCKED의 차이점은 무엇입니까?

Thread.State 문서 :

차단됨
모니터 잠금을 기다리면서 차단 된 스레드가이 상태에 있습니다.

Waiting
다른 스레드가 특정 작업을 수행 할 때까지 무기한 대기중인 스레드가이 상태입니다.

나에게 차이점을 설명하지 않습니다.



답변

스레드는 wait()Object를 호출하면 대기 상태가됩니다 . 이를 대기 상태 라고 합니다. 스레드가 대기 상태에 도달하면 다른 스레드가 호출 될 때까지 notify()또는 notifyAll()객체 에서 기다려야 합니다.

이 스레드가 알림을 받으면 실행할 수 없습니다. 다른 스레드도 알림을 notifyAll()받거나 (사용 ) 첫 번째 스레드가 작업을 완료하지 않았기 때문에 기회가있을 때까지 여전히 차단 될 수 있습니다. 이를 차단 상태 라고 합니다. Blocked 상태는 스레드가 객체에 대한 잠금을 획득하려고 시도하고 다른 스레드가 이미 잠금을 보유하고있을 때마다 발생합니다.

다른 스레드가 떠나고이 스레드 기회가되면 JVM 스레딩 메커니즘을 기반으로 작업을 선택하고 실행 상태로 이동 한 후 Runnable 상태로 이동합니다.


답변

차이점은 비교적 간단합니다.

에서 BLOCKED상태, 스레드가 입력하는 것입니다 synchronized블록을하지만, 현재 내에서 실행중인 다른 스레드가 synchronized같은 객체에 블록. 첫 번째 스레드는 두 번째 스레드가 블록을 종료 할 때까지 기다려야합니다.

에서 WAITING 상태, 스레드는 다른 스레드로부터 신호를 기다리고있다. 이것은 호출하여 일반적으로 발생 Object.wait(), 또는 Thread.join(). 그러면 스레드는 다른 스레드가를 호출 Object.notify()하거나 죽을 때까지이 상태를 유지 합니다.


답변

차단 상태와 대기 상태의 중요한 차이점은 스케줄러에 미치는 영향입니다. 차단 된 상태의 스레드가 잠금을 위해 경쟁하고 있습니다. 해당 스레드는 여전히 스케줄러가 서비스해야하는 것으로 간주되어 실행중인 스레드를 제공 할 시간에 대한 스케줄러의 결정에 고려 될 수 있습니다 (스레드가 잠금을 차단할 기회를 줄 수 있음).

스레드가 대기 상태에 있으면 시스템에 가해지는 스트레스가 최소화되고 스케줄러는 이에 대해 걱정할 필요가 없습니다. 알림을받을 때까지 휴면 상태가됩니다. OS 스레드를 점유하고 있다는 사실을 제외하고는 완전히 작동하지 않습니다.

이것이 notifyAll을 사용하는 것이 이상적이지 않은 이유입니다. 이전에는 시스템에 부하를주지 않고 휴면 상태였던 스레드가 깨어나고 대부분의 스레드가 잠금을 획득하고 상태를 찾을 때까지 차단됩니다. 기다리는 것은 사실이 아니므로 다시 기다리십시오. 진행할 가능성이있는 스레드에만 알리는 것이 좋습니다.

(내재 잠금 대신 ReentrantLock을 사용하면 하나의 잠금에 대해 여러 조건을 가질 수 있으므로 알림 스레드가 특정 조건에서 대기중인 스레드인지 확인하여 스레드가 알림을받는 경우 분실 알림 버그를 방지 할 수 있습니다. 행동 할 수없는 것.)


답변

스레드 덤프 해석을위한 단순화 된 관점 :

  • 잠깐만 -일을 기다리고있어서 지금은 게으른 상태입니다.
  • 차단됨 -작업을 완료하려고 바쁘지만 다른 스레드가 방해가되어 지금은 유휴 상태입니다.
  • RUNNABLE … (Native Method) -JVM에 관한 한 일부 네이티브 코드 (아직 완료되지 않은)를 실행하도록 요청했습니다. RUNNABLE이며 추가 정보를 제공 할 수 없습니다. 일반적인 예는 실제로 트래픽이 도착하기를 기다리는 C로 코딩 된 네이티브 소켓 리스너 메서드이므로 지금은 유휴 상태입니다. 이 상황에서 이것은 우리가 실제로 RUNNING (CPU 소모 없음)이 아니기 때문에 특별한 종류의 WAIT로 볼 수 있지만이를 보려면 Java 스레드 덤프가 아닌 OS 스레드 덤프를 사용해야합니다.

답변

차단됨-스레드가 스레드 수명주기의 실행 가능한 상태에 있으며 개체 잠금을 얻으려고합니다. Wait- 스레드가 스레드 수명주기의 대기 상태에 있으며 알림 신호가 스레드의 실행 가능 상태가되기를 기다리고 있습니다.


답변

이 예를 참조하십시오.

스레드 상태의 데모.

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


답변