线程状态WAIT和线程状态BLOCKED之间有什么区别?
阻止 被阻塞等待监视器锁定的线程处于此状态。
等候 无限期等待另一个线程执行特定操作的线程处于此状态
没有解释给我的区别。
一旦线程在对象上调用wait()
,线程就会进入等待状态。这称为等待国。一旦线程到达等待状态,它将需要等待一些其他线程调用对象上的notify()
或notifyAll()
。
一旦通知此线程,它将无法运行。可能是其他线程也被通知(使用notifyAll()
)或者第一个线程还没有完成他的工作,所以它仍然被阻塞,直到它有机会。这称为阻塞状态。只要线程试图获取对象的锁定而某些其他线程已经持有锁,就会发生阻塞状态。
一旦其他线程离开并且这个线程有机会,它就会移动到Runnable状态,之后它就是基于JVM线程机制的合格拾取工作并转移到运行状态。
差异相对简单。
在BLOCKED
状态中,线程即将进入synchronized
块,但是当前在同一对象上的synchronized
块内运行另一个线程。然后第一个线程必须等待第二个线程退出其块。
在WAITING
状态中,线程正在等待来自另一个线程的信号。这通常通过调用Object.wait()
或Thread.join()
来实现。然后线程将保持此状态,直到另一个线程调用Object.notify()
或死亡。
阻塞和等待状态之间的重要区别是对调度程序的影响。处于阻塞状态的线程是争用锁定的waitset的一部分;该线程仍然被视为调度程序需要服务的东西,可能会考虑到调度程序决定给出运行线程的时间。
一旦线程处于等待状态,它对系统施加的压力就会最小化,并且调度程序不必担心它。它会一直处于休眠状态,直到收到通知为止。除了它保持OS线程占用的事实之外,它完全没有用。
这就是为什么使用notifyAll不太理想的原因,它导致一堆以前很高兴休眠的线程在系统上没有负载被唤醒,其中大多数线程将阻塞直到他们可以获得锁定,找到它们的条件等待不是真的,回去等待。最好只通知那些有可能取得进展的线程。
(使用ReentrantLock而不是内部锁定允许您为一个锁定具有多个条件,这样您就可以确保通知的线程正在等待特定条件的线程,避免在线程获得通知的情况下丢失通知错误它无法作用的东西。)
解释线程转储的简化透视图:
已阻止 - 您的线程处于线程生命周期的可运行状态并尝试获取对象锁定。等待 - 您的线程处于线程生命周期的等待状态,并等待通知信号进入线程的可运行状态。
看这个例子:
线程状态的演示。
/*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();
}
}
}
}