线程状态WAIT和线程状态BLOCKED有什么区别?
线程。官方文档:
阻塞
等待监视器锁定的线程处于此状态。
正在无限期等待另一个线程执行特定操作的线程处于此状态
调用对象的wait()
后,线程进入等待状态。这被称为Waiting State。一旦线程达到等待状态,它将需要等待,直到其他线程调用对象上的notify()
或notifyAll()
。
一旦这个线程被通知,它将不能运行。可能是其他线程也被通知了(使用notifyAll()
),或者第一个线程还没有完成它的工作,所以它仍然被阻塞,直到它得到机会。这被称为Blocked State。当一个线程试图获取对象上的锁而其他线程已经持有该锁时,就会发生阻塞状态。
一旦其他线程离开并且该线程有机会,它将移动到Runnable状态,之后它有资格根据JVM线程机制拾取工作并移动到运行状态
区别比较简单。
在BLOCKED
状态下,一个线程即将进入synchronized
块,但是在同一个对象上的synchronized
块中有另一个线程正在运行。然后,第一个线程必须等待第二个线程退出它的块。
在WAITING
状态下,一个线程正在等待另一个线程的信号。这通常通过调用Object.wait()
或Thread.join()
来实现。然后,该线程将保持这种状态,直到另一个线程调用Object.notify()
或死亡。
阻塞状态和等待状态之间的重要区别是对调度程序的影响。处于阻塞状态的线程正在争用锁;这个线程仍然是调度器需要服务的对象,可能会在调度器决定给正在运行的线程多少时间时被考虑在内(这样它就可以给阻塞在锁上的线程一个机会)。
一旦线程处于等待状态,它给系统带来的压力就最小化了,调度器不必担心它。它在收到通知之前处于休眠状态。除了它占用了一个操作系统线程之外,它是完全不工作的。
这就是为什么使用notifyAll不太理想的原因,它会导致一堆以前愉快地休眠的线程在系统上没有负载被唤醒,其中大多数线程将阻塞,直到它们可以获得锁,发现它们正在等待的条件不为真,并返回等待。最好只通知那些有机会取得进展的线程。
(使用ReentrantLock而不是固有锁允许您为一个锁设置多个条件,因此您可以确保被通知的线程正在等待特定条件,从而避免在线程因无法操作的事情而收到通知的情况下丢失通知错误。)
解释线程转储的简化透视图:
-
WAIT -我正在等待一些工作,所以我现在是空闲的。
-
BLOCKED -我正忙着完成工作,但另一个线程挡住了我的路,所以我现在空闲
- RUNNABLE …(本机方法)-我调用运行一些本机代码(还没有完成),所以就JVM而言,你是RUNNABLE的,它不能提供任何进一步的信息。
C
中编码的本机套接字侦听器方法,它实际上正在等待任何流量到达,所以我现在是空闲的。在这种情况下,这可以被看作是一种特殊的WAIT
,因为我们实际上不是RUNNING
(没有CPU消耗),但是你必须使用操作系统线程转储而不是Java线程转储来查看它。
Blocked-你的线程处于线程生命周期的可运行状态,并试图获得对象锁。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();
}
}
}
}