线程状态概述
在API中java.lang.Thread.State
这个枚举给了6种线程状态:
线程状态 | 导致状态发生条件 |
---|---|
NEW(新建) | 线程刚被创建,但是并未启动。还没调用start方法。 |
Runnable(可运行) | 线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理器。 |
Waiting(无限等待) | 一个线程在等待另一个线程执行一个(唤醒) 动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者ntifyll方法才能够唤醒。 |
TimedWaiting(计时等待) | 同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep、Object.wait. |
Teminated(被终止) | 因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。 |
Timed Wating(计时等待)
- Timed Waiting在API中的描述为: 一个正在限时等待另一个线程执行一个(唤醒)动作的线程处于这一状态。
- 在前面写卖票的案例中,为了减少线程执行太快,现象不明显等问题,在run方法中添加了sleep语句, 这样就强制当前正在执行的线程休眠(暂停执行),以"减慢线程”。
- 当调用了sleep方法之后, 当前执行的线程就进入到“休眠状态",就是所谓的Timed Waiting(计时等待)。
注意:
- 进入TIMED. WAITING状态的一种常见情形是调用的sleep方法,单独的线程也可以调用,不-定非要有协
作关系。 - 为了让其他线程有机会执行,可以将Thread.sleep()的调用放线程run()之内。 这样才能保证该线程执行过程
中会睡眠 - sleep与锁无关, 线程睡眠到期自动苏醒,并返回到Runnable (可运行)状态。
Timed Waiting线程状态图:
Blocked(锁阻塞)
- Blocked状态在API中的介绍为:一个正在阻塞等待一个监视器锁 (锁对象)的线程处于这一状态。比如,线程A与线程B代码中使用同一锁,如果线程A获取到锁,线程A进入到Runnable状态,那么线程B就进入到Blocked锁阻塞状态。
- 这是由Runnable状态进入Blocked状态。除此Waiting以及 Time Waiting状态也会在某种情况下进入阻塞状态。
Blocked线程状态图
Waiting无限等待
- Wating状态在API中介绍为: 一个正在无限期等待另一个线程执行一个特别的(唤醒)动作的线程处于这一状态。
案例演示:
public class Demo04Waiting {
//创建锁对象
public static Object obj = new Object();
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
while (true){
synchronized (obj){
System.out.println("顾客点菜");
System.out.println("点完菜,等待上菜........");
try {
//进入无线等待,等待老板做菜
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
synchronized (obj) {
try {
Thread.sleep(3000);//等待5秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("菜做好了");
obj.notify();
}
}
}
}).start();
}
}
- 通过上述案例发现,一个调用了某个对象的Objet.wait方法的线程会等待另一个线程调用此对象的object.notify()方法或0bject.ntifyll()方法。
- waiting状态并不是一个线程的操作, 它体现的是多个线程间的通信,可以理解为多个线程之间的协作关系,多个线程会争取锁,同时相互之间又存在协作关系。
- 当多个线程协作时,比如A, B线程,如果A线程在Runnable (可运行)状态中调用了wait()方法那么A线程就进入了Waiting (无限等待)状态,同时失去了同步锁。假如这个时候B线程获取到了同步锁,在运行状态中调用了notify()方法,那么就会将无限等待的A线程唤醒。注意是唤醒,如果获取到锁对象,那么A线程唤醒后就进入Runnable (可运行)状态;如果没有获取锁对象,那么就进入到Blocked (锁阻塞状态)。
Waiting线程状态图