文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java多线程之等待唤醒机制及案例代码演示

2023-10-25 11:16

关注

生产者和消费者(等待唤醒机制)

等待唤醒机制

生产者和消费者是一个十分经典的多线程协作模式

举个小栗子来说明一下消费者和生产者的等待唤醒过程:
在这里插入图片描述

常见方法

在这里插入图片描述

代码演示

接下来,使用代码来演示生产者和消费者的等待唤醒过程

1、消费者代码:

package com.heima.thread001;public class FoodThread extends Thread {    @Override    public void run() {        while (true){            synchronized (Desk.lock){                if (Desk.count == 0){                    break;                }else {                    //判断桌子上有没有面条                    if (Desk.foodFlag == 0){                        //如果没有,就等待                        try {Desk.lock.wait();//让当前线程跟锁进行绑定                        } catch (InterruptedException e) {e.printStackTrace();                        }                    }else {                        //把吃的总数-1                        Desk.count--;                        //如果有,就开吃                        System.out.println("吃货在吃面条,还能再吃" + Desk.count + "碗");                        //吃完之后,唤醒厨师继续做                        Desk.lock.notifyAll();                        //修改桌子的状态                        Desk.foodFlag = 0;                    }                }            }        }    }}

2、生产者代码

package com.heima.thread001;public class CookThread extends Thread {    @Override    public void run() {        while (true){            synchronized (Desk.lock){                //判断桌子上有没有面条                if (Desk.count == 0){                    break;                }else {                    //判断桌子上是否有实物                    if(Desk.foodFlag == 1){                        //如果有,就等待                        try {Desk.lock.wait();                        } catch (InterruptedException e) {e.printStackTrace();                        }                    }else {                        //如果没有,就制作面条                        System.out.println("厨师做了一碗面条");                        //修改桌子上的食物状态                        Desk.foodFlag = 1;                        //叫醒等待的消费者开吃                        Desk.lock.notifyAll();                    }                }            }        }    }}

3、控制生产者和消费者的执行类

package com.heima.thread001;public class Desk {        //是否有面条  0:没有面条  1:有面条    public static int foodFlag = 0;    //总个数    public static int  count = 10;    //锁对象    public static Object lock = new Object();}

4、测试类

package com.heima.thread001;public class TestDemo {    public static void main(String[] args){        CookThread cookThread = new CookThread();        FoodThread foodThread = new FoodThread();        cookThread.setName("厨师");        foodThread.setName("吃货");        cookThread.start();        foodThread.start();    }}

5、运行结果

Connected to the target VM, address: '127.0.0.1:52025', transport: 'socket'Disconnected from the target VM, address: '127.0.0.1:52025', transport: 'socket'厨师做了一碗面条吃货在吃面条,还能再吃9碗厨师做了一碗面条吃货在吃面条,还能再吃8碗厨师做了一碗面条吃货在吃面条,还能再吃7碗厨师做了一碗面条吃货在吃面条,还能再吃6碗厨师做了一碗面条吃货在吃面条,还能再吃5碗厨师做了一碗面条吃货在吃面条,还能再吃4碗厨师做了一碗面条吃货在吃面条,还能再吃3碗厨师做了一碗面条吃货在吃面条,还能再吃2碗厨师做了一碗面条吃货在吃面条,还能再吃1碗厨师做了一碗面条吃货在吃面条,还能再吃0Process finished with exit code 0

等待唤醒机制(阻塞队列方式实现)

在这里插入图片描述
阻塞队列的继承结构
在这里插入图片描述
代码演示:
生产者代码

package com.heima.thread001;import java.util.concurrent.ArrayBlockingQueue;public class CookThread extends Thread {    ArrayBlockingQueue<String> queue;    public CookThread(ArrayBlockingQueue<String> queue){        this.queue = queue;    }    @Override    public void run() {        while (true){            //不断把面条放到阻塞队列中            try {                queue.put("面条");                System.out.println("厨师放了一碗面条");            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

消费者

package com.heima.thread001;import java.util.concurrent.ArrayBlockingQueue;public class FoodThread extends Thread {    ArrayBlockingQueue<String> queue;    public FoodThread(ArrayBlockingQueue<String> queue){        this.queue = queue;    }    @Override    public void run() {        while (true){            //不断的从阻塞队列中获取面条            try {                String food = queue.take();                System.out.println(food);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

测试类

package com.heima.thread001;import java.util.concurrent.ArrayBlockingQueue;public class TestDemo {    public static void main(String[] args){        ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(1);        CookThread c = new CookThread(queue);        FoodThread f = new FoodThread(queue);        c.start();        f.start();    }}

额外扩展

wait()、notify()、notifyAll()方法
Object类里面提供了这几个方法:
wait():让当前线程处于等待(阻塞状态),直到其他线程调用此对象的notify()或notifyAll()方法(进入就绪状态)。
notify():唤醒在此对象监视器上等待的单个线程。
notifyAll():唤醒在此对象监视器上等待的所有线程。
每个方法都有finnal关键字修饰。

为什么这些方法要定义在Object类里,而不定义在Thread类里呢?
因为这些方法的调用必须通过锁对象调用,而锁对象可以是任意对象。所以定义在Object类里。

来源地址:https://blog.csdn.net/weixin_43860634/article/details/133611415

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯