线程的状态描述
线程一共有6种状态:在Thread的子类中Thread.State类中记载了线程的6种状态
线程状态图描述:图片来自某网课,如侵权请联系删除

线程状态。线程可以处于以下状态之一:
NEW
尚未启动的线程处于此状态。
RUNNABLE
在Java虚拟机中执行的线程处于此状态。
BLOCKED
被阻塞等待监视器锁定的线程处于此状态。
WAITING
正在等待另一个线程执行特定动作的线程处于此状态。
TIMED_WAITING
正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
TERMINATED
已退出的线程处于此状态。

线程状态通信案例(生产者-消费者问题)实现线程状态的互相转换: Waiting ⇒Runnable
/*
*
* 等待唤醒案例分析:线程之间的通信
* step1:创建一个顾客线程(消费者):告知老板食物的数量和种类,然后调用wait方法时顾客线程进入waiting状态
* step2:创建一个老板线程(生产者):花了5秒钟做食物,并用notify来唤醒顾客让其食用
*
* 注意:生产者和消费者必须使用同步代码块,保证等待和唤醒在同一时刻只能有一个在执行
* 同步使用的锁对象必须要唯一
* 只有锁对象才能调用wait和notify方法
* Object类中的wait和notify方法
* void wait()
导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
* void notify()
唤醒正在等待对象监视器的单个线程。
* 唤醒之后会执行wait之后的代码
*
* */
public class DemoWaitandNortify {
public static void main(String[] args) {
//创建一个锁对象 并且唯一
Object obj = new Object();
//创建一个顾客线程(消费者)
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
synchronized (obj){
System.out.println("告知老板食物的数量和种类");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("wait之后就开吃");
}
}
}
}).start();
new Thread(){
@Override
public void run() {
while (true){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj){
System.out.println("花了5秒钟做食物后,唤醒顾客让其食用");
obj.notify();
}
}
}
}.start();
}
}
Timed-Waiting状态
/*
* 进入到Timed-Waiting有两种方式,
* 1.调用Thread中的方法sleep(long millis)
使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。
* 当sleep在参数的毫秒之后会进入到Running|Blocked状态
* 2.调用Object带参数的wait(long timeout)
导致当前线程等待,直到另一个线程调用 notify()方法或该对象的 notifyAll()方法,或者指定的时间已过。
* 如果在指定的毫秒值之后还未被notify那么就会自动醒来
* */
public class DemoTimedWaiting {
public static void main(String[] args) {
//创建一个锁对象 并且唯一
Object obj = new Object();
//创建一个顾客线程(消费者)
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
synchronized (obj){
System.out.println("告知老板食物的数量和种类");
try {
obj.wait(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("wait之后就开吃");
}
}
}
}).start();
}
}
notify vs notifyAll
public static void main(String[] args) {
//创建一个锁对象 并且唯一
Object obj = new Object();
//创建一个顾客1线程(消费者)
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
synchronized (obj){
System.out.println("顾客1告知老板食物的数量和种类");
try {
obj.wait(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("顾客1wait之后就开吃");
}
}
}
}).start();
//创建一个顾客2线程(消费者)
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
synchronized (obj){
System.out.println("顾客2告知老板食物的数量和种类");
try {
obj.wait(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("顾客2wait之后就开吃");
}
}
}
}).start();
//创建一个老板线程(生产者)
new Thread(){
@Override
public void run() {
while (true){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj){
System.out.println("花了5秒钟做食物后,唤醒顾客让其食用");
//obj.notify();//只能唤醒一个,当有两个以上的线程处于等待的状态就随机唤醒
obj.notifyAll();//把两个线程都唤醒,但由于1个生产者两消费者,会顾不过来,打印也会混乱
}
}
}
}.start();
}
顾客1告知老板食物的数量和种类
顾客2告知老板食物的数量和种类
顾客2wait之后就开吃
顾客2告知老板食物的数量和种类
花了5秒钟做食物后,唤醒顾客让其食用
顾客1wait之后就开吃
顾客1告知老板食物的数量和种类
顾客2wait之后就开吃
顾客2告知老板食物的数量和种类
顾客1wait之后就开吃
顾客1告知老板食物的数量和种类
顾客2wait之后就开吃
顾客2告知老板食物的数量和种类
花了5秒钟做食物后,唤醒顾客让其食用
顾客2wait之后就开吃
顾客2告知老板食物的数量和种类
顾客1wait之后就开吃
顾客1告知老板食物的数量和种类
顾客1wait之后就开吃
顾客1告知老板食物的数量和种类
花了5秒钟做食物后,唤醒顾客让其食用
顾客2wait之后就开吃
顾客2告知老板食物的数量和种类
顾客1wait之后就开吃
顾客1告知老板食物的数量和种类