Java学习日志(十二): 线程状态,等待与唤醒案例

JavaEE学习日志持续更新----> 必看!JavaEE学习路线(文章总汇)

线程状态

在API中 java.lang.Thread.State 这个枚举中给出了六种线程状态:

线程状态 导致状态发生条件
NEW(新建) 线程刚被创建,但是并未启动。还没调用start方法。
Runnable(可运行) 线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理器。
Blocked(锁阻塞) 当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。
Waiting(无限等待) 一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。
Timed Waiting(计时等待) 同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、 Object.wait。
Teminated(被 终止) 因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。

在这里插入图片描述

等待与唤醒案例(包子铺案例)

等待与唤醒:线程之间的通信
Object类中的方法

  • void wait() 导致当前线程等待它被唤醒,通常是通知或中断 。
  • void notify() 唤醒正在此对象监视器(对象锁)上等待的单个线程。

注意:

  1. wait和notify方法必须由锁对象调用(必须是同个锁对象
    锁对象–>wait() 锁对象–>notify()
  2. wait和notify方法一般写在同步中

案例:包子铺案例

需求
两大线程:设线程A(包子铺),执行生产包子的动作。线程B(吃货),执行吃包子的操作

共享资源:包子

执行动作:生产一个包子,吃一个包子

分析
包子的状态进行分析
没有包子:吃货线程唤醒包子铺线程—>吃货线程等待—>包子铺线程做包子—>包子铺做好包子—>修改包子的状态—>有包子
有包子:包子铺唤醒吃货线程—>包子铺线程等待—>吃货吃包子—>修改包子的状态—>没有包子
…(循环)

扫描二维码关注公众号,回复: 9038080 查看本文章

代码实现:

资源类:包子,其中有皮,陷,包子的状态

public class BaoZi {
    String pi;
    String xian;
    //包子状态,初始值为false,没有包子
    boolean flag = false;
}

包子铺类:是一个线程类,线程任务:生产包子

对包子的状态进行判断:
true:有包子
        包子铺线程调用wait等待
false:没有包子
        包子铺线程生产包子
        生产x皮x陷的包子
        生产包子花费3秒
        生产完包子,修改包子状态为true
        包子铺线程唤醒吃货线程,吃包子

注意:

  1. 生产包子和吃包子,只能有一个在执行,需要使用同步技术
  2. 同步技术需要使用锁对象,可以使用包子对象
    在成员位置创建一个包子对象
    使用构造方法为包子变量赋值
public class BaoZiPu implements Runnable {
    //在成员位置创建一个包子对象
    BaoZi bz;
    //使用构造方法为包子变量赋值
    public BaoZiPu(BaoZi bz) {
        this.bz = bz;
    }

    //线程任务:生产包子
    @Override
    public void run() {
        while(true){
/*
            1.生产包子和吃包子,只能有一个在执行,需要使用同步技术
            2.同步技术需要使用锁对象,可以使用包子对象
         */
            synchronized (bz){
                //对包子状态进行判断
                if(bz.flag==true){
                    //true:有包子
                    //            包子铺线程调用wait等待
                    try {
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //包子铺被吃货唤醒之后执行的代码
                //false:没有包子,包子铺线程生产包子
                //生产x皮x陷的包子
                bz.pi = "薄皮";
                bz.xian = "玉米鲜肉";
                System.out.println("包子铺正在生产"+bz.pi+bz.xian+"的包子!");
                //生产包子花费3秒
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //生产完包子,修改包子状态为true
                bz.flag = true;
                //包子铺线程唤醒吃货线程,吃包子
                bz.notify();
                System.out.println("包子铺已经生产好"+bz.pi+bz.xian+"的包子!");
            }
        }
    }
}

吃货类:是一个线程类,线程任务:吃包子

对包子的状态进行判断:
false:没有包子
    吃货线程调用wait等待
true:有包子
    吃货线程开始吃包子
    打印吃x皮x陷的包子
    吃完包子,修改包子的状态为false
    吃货线程唤醒包子铺线程,做包子

注意:

  1. 生产包子和吃包子,只能有一个在执行,需要使用同步技术
  2. 同步技术需要使用锁对象,可以使用包子对象
    在成员位置创建一个包子对象
    使用构造方法为包子变量赋值
public class ChiHuo implements Runnable{
    //在成员位置创建一个包子对象
    BaoZi bz;
    //使用构造方法为包子变量赋值
    public ChiHuo(BaoZi bz) {
        this.bz = bz;
    }

    //线程任务:吃包子
    @Override
    public void run() {
        while (true){
            /*
            1.生产包子和吃包子,只能有一个在执行,需要使用同步技术
            2.同步技术需要使用锁对象,可以使用包子对象
         */
            synchronized (bz){
                //对包子的状态进行判断
                //        false:没有包子
                if (bz.flag==false){
                    //吃货线程调用wait等待
                    try {
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            /*
                吃货线程被包子铺线程唤醒之后执行的代码
             */
                //true:有包子,吃货线程开始吃包子
                //打印吃x皮x陷的包子
                System.out.println("吃货正在吃"+bz.pi+bz.xian+"的包子!");
                //吃完包子,修改包子的状态为false
                bz.flag = false;
                //吃货线程唤醒包子铺线程,做包子
                bz.notify();
                System.out.println("吃货已经吃完了"+bz.pi+bz.xian+"的包子!包子铺赶紧生产包子!");
                System.out.println("-----------------------");
            }
        }
    }
}

测试类
创建一个包子对象
创建一个包子铺线程,生产包子
创建一个吃货线程,吃包子

public class Demo01 {
    public static void main(String[] args) {
        //创建一个包子对象
        BaoZi bz = new BaoZi();
        //创建一个包子铺线程,生产包子
        new Thread(new BaoZiPu(bz)).start();
        //创建一个吃货线程,吃包子
        new Thread(new ChiHuo(bz)).start();
    }
}

运行结果:

包子铺正在生产薄皮玉米鲜肉的包子!
包子铺已经生产好薄皮玉米鲜肉的包子!
吃货正在吃薄皮玉米鲜肉的包子!
吃货已经吃完了薄皮玉米鲜肉的包子!包子铺赶紧生产包子!
-----------------------
包子铺正在生产薄皮玉米鲜肉的包子!
包子铺已经生产好薄皮玉米鲜肉的包子!
吃货正在吃薄皮玉米鲜肉的包子!
吃货已经吃完了薄皮玉米鲜肉的包子!包子铺赶紧生产包子!
-----------------------
...
发布了16 篇原创文章 · 获赞 17 · 访问量 1834

猜你喜欢

转载自blog.csdn.net/Sakuraaaaaaa/article/details/104234964