WAIT和BLOCKED线程状态之间的区别

时间:2013-03-28 11:18:46

标签: java multithreading block wait

线程状态WAIT和线程状态BLOCKED有什么区别?

Thread.State documentation

  

阻止
  被阻塞等待监视器锁定的线程处于此状态。

     

等待
  无限期等待另一个线程执行特定操作的线程处于此状态

并不能解释我与众不同之处。

6 个答案:

答案 0 :(得分:76)

差异相对简单。

BLOCKED状态下,线程即将进入synchronized块,但是当前在同一对象的synchronized块内运行另一个线程。然后第一个线程必须等待第二个线程退出其阻塞。

WAITING状态下,线程正在等待来自另一个线程的信号。这通常是通过调用Object.wait()Thread.join()来实现的。然后线程将保持此状态,直到另一个线程调用Object.notify()或死亡。

答案 1 :(得分:59)

线程在对象上调用wait()后进入等待状态。这称为等待状态。一旦线程到达等待状态,它将需要等到其他线程调用对象上的notify()notifyAll()

通知此线程后,它将无法运行。可能是其他线程也被通知(使用notifyAll())或第一个线程尚未完成其工作,因此它仍然被阻塞,直到它有机会。这称为阻止状态。只要线程试图获取对象的锁定而某些其他线程已经持有锁,就会发生阻塞状态。

一旦其他线程离开并且这个线程有机会,它就会转移到Runnable状态,之后它就是基于JVM线程机制的合格拾取工作并转移到运行状态。

答案 2 :(得分:12)

阻塞状态和等待状态之间的重要区别是对调度程序的影响。处于阻塞状态的线程是争用锁定的waitset的一部分;该线程仍然被视为调度程序需要服务的东西,可能会考虑调度程序决定给出运行线程的时间。

一旦线程处于等待状态,它对系统施加的压力就会最小化,而调度程序也不必担心它。它会一直处于休眠状态,直到收到通知为止。除了保持OS线程占用的事实之外,它完全没有用。

这就是为什么使用notifyAll不太理想,它会导致一堆以前很高兴休眠的线程在系统上没有负载被唤醒,其中大多数线程会阻塞,直到他们可以获得锁定,找到他们等待的条件不是真的,回去等待。最好只通知那些有可能取得进展的线程。

(使用ReentrantLock代替内部锁定允许您为一个锁定具有多个条件,以便您可以确保通知的线程是在特定条件下等待的线程,避免在线程的情况下丢失通知错误收到无法接受通知的通知。)

答案 3 :(得分:10)

解释线程转储的简化透视图:

  • 等待 - 我等着接受一些工作,所以我现在闲着。
  • BLOCKED - 我正忙着完成工作,但是另一个线程阻碍了我,所以我现在正在闲着。
  • RUNNABLE ...(本机方法) - 我调用了一些本机代码(尚未完成),所以就JVM而言,你是RUNNABLE而且它无法提供任何进一步的信息。一个常见的例子是用C编码的本机套接字监听器方法,它实际上在等待任何流量到达,所以我现在正在闲置。在这种情况下,这可以看作是一种特殊的WAIT,因为我们实际上并没有RUNNING(没有CPU刻录),但你必须使用OS线程转储而不是Java线程转储才能看到它。

答案 4 :(得分:1)

已阻止 - 您的线程处于线程生命周期的可运行状态并尝试获取对象锁定。 等待 - 您的线程处于线程生命周期的等待状态,并等待通知信号进入线程的可运行状态。

答案 5 :(得分:-1)

见这个例子:

演示线程状态。

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