java进阶—线程间通信(通俗易懂等待唤醒机制)

news2024/11/22 19:50:02

今天我们来看一看,线程之间的通信,也就是我们所说的等待唤醒机制

先来看三个关键方法:

wait();

当线程执行这个方法,它就会进入阻塞状态,并且释放同步监视器

notify();

英文翻译 唤醒,就是说会唤醒wait的线程,注意一点,是唤醒别人,不是唤醒自己,A进入wait 状态 ,需要 B 执行notify 方法去唤醒A,很好理解,你睡着了,不能自己叫醒自己,得闹钟或者别人叫醒你,自然醒那是 sleep()、

如果有多个线程进入阻塞状态,就会唤醒优先级较高的线程

notifyAll();

加了个all,唤醒全部,所有被阻塞的线程全部唤醒

这边举一个通俗的例子:不知道大家小时候有没有玩过 类似 ”全国人民大解放“ 的游戏 ,一个小朋友抓,其他跑,快要被抓住,喊出什么话(这边具体是什么忘了),就不能动了(这边类似你进入wait),得等到别人来拍你,(一般都是会先拍比较厉害的那一个)你才能动 (这边类似notify,别人来唤醒你) ,当仅剩下一个小伙伴在活动,就可以喊出 “全国人民大解放” ,所有人都可以活动(这就类似 notifyAll)

到这,应该对于等待唤醒机制比较了解了

直接上代码,通过代码我们来看看是怎么一回事

比如:

模拟两个线程进行交替打印1-10

首先我们来看看线程没有进行通信,两个线程进行资源抢占的情况:


public class Demo  implements Runnable{
    int  num = 1;

    @Override
    public void run() {
       while (true) {
           synchronized (this) {
               if (num<=10) {
                   System.out.println(Thread.currentThread().getName()+":"+num);
                   num++;
               } else {
                   break;
               }
           }

       }
    }


    public static void main(String[] args) {
            Demo demo =new Demo();
            Thread thread1 =new Thread(demo,"线程1");
            Thread thread2 =new Thread(demo,"线程2");
            thread1.start();
            thread2.start();
    }
}

在这里插入图片描述
可以看到所有资源都被线程1抢占,不符合我们的需求

接下来看看两个线程间进行通信后的结果


public class Demo  implements Runnable{
    int  num = 1;

    @Override
    public void run() {
       while (true) {
           synchronized (this) {
               notify();
               if (num<=10) {
                   System.out.println(Thread.currentThread().getName()+":"+num);
                   num++;
                   try {
                       //使线程进入阻塞
                       wait();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               } else {
                   break;
               }
           }

       }
    }


    public static void main(String[] args) {
            Demo demo =new Demo();
            Thread thread1 =new Thread(demo,"线程1");
            Thread thread2 =new Thread(demo,"线程2");
            thread1.start();
            thread2.start();
    }
}

在这里插入图片描述
在这里插入图片描述
线程间通信就引出了一个生产者,消费者的问题

就比如去饭店吃饭,得有饭才能去吃

生产者:Productor


public class Productor  implements Runnable{

    List<String> list  = new ArrayList<>();

    public Productor(List<String> list) {
        this.list = list;
    }


    @Override
    public void run() {
        int num = 0;
        while (true) {
            synchronized (list) {
                if (list.size() == 0) {
                    num++;
                    //没有饭生产
                    list.add("第" + num + "份米饭");
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "生产了" + list.get(0));
                    list.notify();
                } else {
                    // 有饭等待消费者消费
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        }
    }
}

消费者:


public class Consumer  implements Runnable{

    List<String> list;

    public Consumer(List<String> list) {
        this.list = list;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (list) {
                if (list.size() > 0) {
                    //有饭消费,并通知生产者
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "消费了" + list.get(0));
                    list.remove(0);
                    list.notify();
                } else {
                    //无饭等待
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

进行创建线程

 public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        Productor productor =new Productor(list);
        Consumer consumer =new Consumer(list);

        new Thread(productor,"小红").start();
        new Thread(consumer,"小明").start();

    }

输出结果:

在这里插入图片描述
以上就是等待唤醒机制的全部内容了

在这里插入图片描述
java进阶—多线程

java 进阶—线程的常用方法

java进阶—线程安全问题

Java 进阶—死锁造成原因及其解决

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/631104.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【 图像分割 2022 ECCV】CP2

【 图像分割 2022 ECCV】CP2 论文题目&#xff1a;CP2: Copy-Paste Contrastive Pretraining for Semantic Segmentation 中文题目&#xff1a;CP2:语义分割的复制粘贴对比预训练 论文链接&#xff1a;https://arxiv.org/abs/2203.11709 论文代码&#xff1a;https://github.co…

Python3+Selenium框架搭建

Webdriver概述 Webdriver (Selenium2&#xff09;是一种用于Web应用程序的自动测试工具&#xff0c; Thoughtworks公司一个强大的基于浏览器的开源自动化测试工具&#xff0c;通常用来编写web应用的自动化测试。 Selenium 是一个用于Web应用程序测试的工具。 Selenium测试直…

异常数据检测 | Python实现支持向量机(SVM)的异常数据检测

文章目录 文章概述模型描述源码分享学习小结参考资料文章概述 SVM通常应用于监督式学习,但OneClassSVM算法可用于将异常检测这样的无监督式学习,它学习一个用于异常检测的决策函数其主要功能将新数据分类为与训练集相似的正常值或不相似的异常值。 模型描述 OneClassSVM的思…

Flink 1.17.0集群搭建

集群角色分配 HostnameIPRolehadoop01192.168.126.132 JobManager TaskManager hadoop02192.168.126.133TaskManagerhadoop03192.168.126.134TaskManager 下载flink安装包 https://archive.apache.org/dist/flink/flink-1.17.0/ 上传至hadoop01并解压&#xff1a; 修改conf/…

微软MFC技术简明介绍

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天来看一下微软MFC技术简明介绍 Visual C 与 MFC 微软公司于1992年上半年推出了C/C 7.0 产品时初次向世人介绍了MFC 1.0&#xff0c;这个产品包含了20,000行C原始代码&#xff0c;60个以上的Windows相关类…

【Leetcode】贪心问题合集 | 摆动序列、K次取反最大和、加油站、分发糖果、柠檬水找零、根据身高重建队列、单调递增的数字

贪心问题感觉还是挺不好想的&#xff0c;因为每一题有每一题的策略&#xff0c;感觉只能尽量做过的记住了。 376 摆动序列 注意&#xff1a;是序列&#xff0c;而不是数组。 求最大摆动序列的长度&#xff0c;即求谷 / 峰的个数。 若走势不为一条直线。 起始count 2&…

LED显示屏静电防护指南

LED显示屏是一种电子设备&#xff0c;对静电敏感。静电放电可能会对LED显示屏的电子元件造成损坏&#xff0c;因此需要采取静电防护措施。以下是LED显示屏静电防护的一些建议和指南&#xff1a; 环境控制&#xff1a;在LED显示屏周围创建适宜的环境条件。控制湿度和温度&#x…

Yolov5(tag v7.0)网络结构解读,以yolov5s为例

最近yolov5用的多&#xff0c;发现确实好用&#xff0c;于是较深入学了一下。下面按照训练的流程梳理一下网络的结构&#xff0c;同时也是自己记一下便于后面查阅。 同时&#xff0c;我也查了一些关于yolov5网络结构介绍的资料&#xff0c;发现大多是v5.0&#xff0c;少数v6.0的…

Linux驱动IO篇——阻塞/非阻塞IO

文章目录 非阻塞IO阻塞IO等待队列等待队列变体 非阻塞IO 在应用程序中&#xff0c;使用open函数打开一个/dev目录下的一个设备文件时&#xff0c;默认是以阻塞的方式打开。 所谓阻塞&#xff0c;就是当我们请求的资源不可用时&#xff08;资源被占用&#xff0c;没有数据到达等…

让车载系统与外部系统无缝对接——掌握SOA跨系统通信技术

车载SOA架构原理 车载 SOA&#xff08;Service-Oriented Architecture&#xff0c;面向服务的架构&#xff09;是一种基于服务的体系结构&#xff0c;旨在提高车载电子系统的可维护性、可扩展性和互操作性。它将车载电子系统划分为独立的、可复用的服务单元&#xff0c;这些服…

NodeJS MongoDB⑦

文章目录 ✨文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持&#x1f618;前言Node&MongoDB 第一步 连接数据库 第二步 创建User Mongodb模型 第三步 简单使用 Mongodb命令 第四步 规范使用 Mongodb命令 &#xff08…

爆款视频批量剪辑生成系统源码部署

创建视频 该接口用于创建抖音视频&#xff08;支持话题, 小程序等功能&#xff09;。该接口适用于抖音。 使用限制 抖音的 OAuth API 以https://open.douyin.com/ 开头。挂载小程序请先完成注册开发者平台账号。创建抖音视频后, 会有一个审核过程, 期间只有自己可见。如果发…

docker数据管理与网络通信

一、管理docker容器中数据 管理Docker 容器中数据主要有两种方式:数据卷(Data Volumes)和数据卷容器( DataVolumes Containers) 。 1、 数据卷 数据卷是一个供容器使用的特殊目录&#xff0c;位于容器中。可将宿主机的目录挂载到数据卷上&#xff0c;对数据卷的修改操作立刻…

leetcode11. 盛最多水的容器(java)

盛最多水的容器 leetcode11. 盛最多水的容器题目描述 解题思路代码演示二叉树专题 leetcode11. 盛最多水的容器 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/container-with-most-water 题目描述 给定一个长度为 n 的…

物联网Lora模块从入门到精通(二) LED灯泡闪烁与呼吸灯

目录 一、前言 二、实践与代码 1.电亮LED1 2.熄灭LED1 3.翻转LED电平 4.LED1与LED2交替闪烁 5.LED1呼吸灯 三、程序代码 一、前言 本篇内容属于新大陆物联网Lora模块开发&#xff0c;使用给定的Lora基础例程&#xff0c;并在其基础上开发完成&#xff0c;并可为其他版本的Lo…

Atcoder Beginner Contest 294

A - Filter AC代码&#xff1a; #include<iostream> #include<algorithm> #include<cstring> using namespace std; int main() {int n;cin>>n;for(int i0;i<n;i){int x;cin>>x;if(x%20)cout<<x<<" ";}return 0; } …

​​INNODB和MyISAM区别

1 存储引擎是MyISAM 如下&#xff1a; CREATE table test_myisam (cli int ) ENGINEMyISAM 存储目录里会有三个文件 test_myisam.frm为“表定义”&#xff0c;是描述数据表结构的文件 test_myisam.MYI文件是表的索引 test_myisam.MYD文件是表的数据 2 存储引擎是INNODB…

LeetCode——比较字符串最小字母出现频次

1、题目 1170. 比较字符串最小字母出现频次 - 力扣&#xff08;Leetcode&#xff09; 定义一个函数 f(s)&#xff0c;统计 s 中&#xff08;按字典序比较&#xff09;最小字母的出现频次 &#xff0c;其中 s 是一个非空字符串。 例如&#xff0c;若 s "dcce"&am…

httprunner 2.x的基本使用(一)

上一章&#xff1a; 下一章&#xff1a; httprunner 2.x的基本使用&#xff08;二&#xff09;_做测试的喵酱的博客-CSDN博客 一、参考地址&#xff1a; 使用说明_httprunner2.0 概述及使用说明 二、介绍 HttpRunner是一款面向 HTTP(S) 协议的通用测试框架&#xff0c;只需…

location.href 和 document.URL 与 document.documentURI

location.href 和 document.URL 与 document.documentURI 相同点 获取到的值相同 不同点 location.hrefurl可以赋值, 效果类似location.assign(url) , 可以后退 document.URL 与 document.documentURI 是只读的, 赋值无效 location.href locationwindow.location true lo…