JVM虚拟机中线程的状态转换图
- new完线程后,各个线程开始抢cpu,抢到的进入运行状态,没有抢到的进入阻塞状态,阻塞状态和运行状态可以相互转换(多个线程一起抢夺cpu的使用权)。
- run出现异常或者结束的话会进入死亡状态。
- 运行状态可以进入睡眠状态,睡眠结束若cpu空闲,进入运行状态,若不空闲,进入阻塞状态。
- 休眠是可以自己醒的,无限等待状态是不能自己醒的,需要借助Object类中的方法
Timed Waiting(计时等待)

锁阻塞状态

等待与唤醒

等待唤醒案例:线程之间的通信
- 创建一个顾客线程(消费者):告知老板要的包子的种类和数量,调用wait方法,放弃cpu的执行,进入到WAITING状态(无限等待)
- 创建一个老板线程(生产者):花了5秒做包子,做好包子之后,调用notify方法,唤醒顾客吃包子
注意:
- 顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行
- 同步使用的锁对象必须保证唯一
- 只有锁对象才能调用wait和notify方法
Obejct类中的方法
void wait()
在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
void notify()
唤醒在此对象监视器上等待的单个线程。
会继续执行wait方法之后的代码
代码实现
public class DemoWaitAndNotify {
public static void main(String[] args) {
//创建一个唯一的锁对象
Object objLock = new Object();
//创建一个顾客:消费者
new Thread() {
@Override
public void run() {
//保证要么是消费者在告诉老板,要么是老板在做,所以需要同步代码块
System.out.println("告诉老板有消费者要吃包子的种类和数量,然后等待....");
synchronized (objLock) {
//消费者等待老板做完
try {
//调用wait方法,放弃cpu的执行,进入到WAITING状态(无限等待)并释放锁
//被醒来之后会继续朝着wait()之后的语句执行
objLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费者吃包子....");
}
}.start();
//创建一个老板,生产者
new Thread() {
@Override
public void run() {
try {
sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//老板在做某一个包子的过程中,不允许顾客再提要求,也不可能让顾客吃,所以也要同步代码块
synchronized (objLock) {
System.out.println("老板5s之后做好了包子,通知顾客");
objLock.notify();
}
}
}.start();
}
}
运行结果
告诉老板有消费者要吃包子的种类和数量,然后等待....
老板5s之后做好了包子,通知顾客
消费者吃包子....
这段代码的执行逻辑是:一开始两个线程共同争夺cpu资源,而生产者线程上来就sleep()。所以一开始一定是消费者执行,执行到wait()时主动释放cpu资源,在接下来的过程中,没有收到notify()的话就不会继续往下执行。所以等到生产者完成包子的生产之后,通知消费者可以恢复了(消费者才能吃)----->线程间的通讯
版权声明:本文为m0_43410048原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。