【Java】详解多线程通信

🌺个人主页:Dawn黎明开始

🎀系列专栏:Java
每日一句:什么都不做,才会来不及

📢欢迎大家:关注🔍+点赞👍+评论📝+收藏⭐️


文章目录

🔐多线程通信

(1).🔓由来

(2).🔓成员方法 

(3).🔓案例引入

(4).🔓代码实现



🔐多线程通信

(1).🔓由来

      现代社会崇尚合作精神,分工合作在日常生活和工作中无处不在。举个简单的例子,例如一条生产线的上下两个工序,它们必须以规定的速率完成各自的工作,才能保证产品在流水线中顺利的流转。如果下工序过慢,会造成产品在两道工序之间的积压,如果上工序过慢,会造成下工序长时间无事可做。在多线程的程序中,上下工序可以看作两个线程,这两个线程之间需要协同完成工作,就需要线程之间进行通信。

思路:

      如果想解决上述线程执行不一致的问题,就需要控制多个线程按照一定的顺序轮流执行,此时就需要让线程间进行通信保证线程任务的协调进行

解决:

      为此,Java在Object类中提供了wait()notify()notifyAll()等方法用于解决线程间的通信问题,因为Java中所有类都是Object类的子类或间接子类,因此任何类的实例对象都可以直接使用这些方法。

(2).🔓成员方法 

说明:

     其中wait()方法用于使当前线程进入等待状态,notify()和notifyAll()方法用于唤醒当前处于等待状态的线程。

注意:

     wait()、notify()和notifyAll()方法的调用者都应该是同步锁对象,如果这三个方法的调用者不是同步锁对象,Java虚拟机就会抛出IllegalMonitorStateException异常。 

(3).🔓案例引入

生产者-消费者问题分析:

  资源:product<=20

  前台店员:Clerk

  A:从生产者线程获取资源

  B:将资源卖给消费者线程

  生产资源:ProducerThread(生产者)

  消费资源:ConsumerThread(消费者)

  测试类:Demo

(4).🔓代码实现

分析:

      A:使用同步机制

      B:线程通信问题:通过Java提供的等待唤醒机制解决。

Object类中提供了三个方法:

      wait():等待,释放锁资源

      notify():唤醒单个线程,从等待的位置继续执行

      notifyAll():唤醒所有线程

代码如下👇🏻 

package Pro;public class Clerk {private int product=20;   //共享资源//从生产者线程获取资源public synchronized void addProduct(){if(product>=20){try {this.wait();//生产者线程等待,释放锁资源} catch (InterruptedException e) {e.printStackTrace();}}else{product++;System.out.println("生产者生产第" + product + "个产品");this.notifyAll();}}//将资源卖给消费者线程public synchronized void sellProduct(){if(product<=0){try {this.wait();//消费者线程等待,释放锁资源} catch (InterruptedException e) {e.printStackTrace();}}else{	System.out.println("消费者消费第"+product+"个产品");product--;this.notifyAll();}}}
package Pro;public class ProducerThread implements Runnable {Clerk clerk;public ProducerThread(Clerk clerk) {super();this.clerk = clerk;}@Overridepublic void run() {while(true){clerk.addProduct();try {Thread.sleep((int)(Math.random()*10)*100);} catch (InterruptedException e) {e.printStackTrace();}}}}
package Pro;public class ConsumerThread implements Runnable {Clerk clerk;public ConsumerThread(Clerk clerk) {super();this.clerk = clerk;}@Overridepublic void run() {while(true){clerk.sellProduct();try {Thread.sleep((int)(Math.random()*10)*100);} catch (InterruptedException e) {e.printStackTrace();}}}}

package Pro;public class Demo {public static void main(String[] args) {Clerk c=new Clerk();new Thread(new ProducerThread(c), "生产者线程甲").start();new Thread(new ProducerThread(c), "生产者线程乙").start();new Thread(new ConsumerThread(c),"消费者线程甲").start();new Thread(new ConsumerThread(c),"消费者线程乙").start();
//		ProducerThread pt =new ProducerThread(c);
//		Thread t1=new Thread(pt, "生产者线程甲");
//		Thread t2=new Thread(pt, "生产者线程乙");
//		ConsumerThread ct =new ConsumerThread(c);
//		Thread t3=new Thread(ct,"消费者线程甲");
//		Thread t4=new Thread(ct,"消费者线程乙");
//		t1.start();
//		t2.start();
//		t3.start();
//		t4.start();}}

思考:

为什么这些方法不定义在Thread类而是Object类中呢?

      这些方法的调用必须通过锁对象调用,而Object类对象代表任意的对象。所以,这些方法必须定义在Object类中。


🌺建议大家亲自动手操作,学编程,多实践练习是提升编程技能的必经之路。

🌺欢迎大家在评论区进行讨论和指正!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

12v24v60v高校同步降压转换芯片推荐

12V/24V/60V 高校同步降压转换芯片推荐&#xff1a; 对于需要高效、稳定、低噪音的降压转换芯片&#xff0c;推荐使用WD5030E和WD5105。这两款芯片都是采用同步整流技术&#xff0c;具有高效率、低噪音、低功耗等优点&#xff0c;适用于各种电子设备。 WD5030E是一款高效率…

Scrapy----Scrapy简介

文章目录 概述与应用背景架构和组件功能和特点社区生态概述与应用背景 Scrapy,一个高效、灵活、且强大的Web爬取框架,被广泛应用于数据抓取和网页内容的结构化提取。它是用Python编写的,支持多平台运行,适用于数据挖掘、在线零售信息收集、历史数据存档等多种场景。Scrapy…

交换排序详讲:冒泡排序+快速排序(多方法+思路+图解+代码)

文章目录 交换排序一.冒泡排序二.快速排序1.挖坑法2.Hoare法 交换排序 根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置将键值较大的记录向序列的尾部移动&#xff0c;键值较小的记录向序列的前部移动。 一.冒泡排序 /*** 冒泡排序* 时间复杂度 n^2* 空间复杂…

R语言——taxize(第二部分)

taxize&#xff08;第二部分&#xff09; 3. taxize 文档中译3.10. classification&#xff08;根据类群ID检索分类阶元层级&#xff09;示例1&#xff1a;传递单个ID值示例2&#xff1a;传递多个ID值示例3&#xff1a;传递单个名称示例4&#xff1a;传递多个名称示例5&#xf…

nvm安装详细教程(卸载旧的nodejs,安装nvm、node、npm、cnpm、yarn及环境变量配置)

文章目录 一、完全卸载旧的nodejs1、打开系统的控制面板&#xff0c;点击卸载程序&#xff0c;卸载nodejs&#xff08;1&#xff09;打开系统的控制面板&#xff0c;点击程序下的卸载程序&#xff08;2&#xff09;找到node.js&#xff0c;鼠标右击出现下拉框&#xff0c;点卸载…

yolov5模型代码怎么修改

yaml配置文件 深度乘积因子 宽度乘积因子 所有版本只有这两个参数的不同&#xff0c;s m l x逐渐加宽加深 各种类型层参数对照 backbone里的各层&#xff0c;在这里解析&#xff0c;只需要改.yaml里的各层参数就能控制网络结构 修改网络结构 第一步&#xff1a;把新加的模块…

【7】Spring Boot 3 集成组件:缓存组件 spring cache + spring data redis

目录 【7】Spring Boot 3 集成组件&#xff1a;缓存组件 spring cache spring data redis什么是缓存抽象声明式注解JSR-107对应SpEL上下文数据 引入依赖cache 支持的缓存类型缓存类型配置NONESIMPLEREDIS自定义配置 CAFFEINE Hazelcast...总结 个人主页: 【⭐️个人主页】 需要…

GUI编程--PyQt5--QTreeWidget

文章目录 树型控件展示数据修改节点数据获取所有节点的数据 Qt模组参考 QWidgets QTreeWidget 树型控件展示数据 展示数据的同时&#xff0c;每个节点标注数据类型。 class MyWindow(QWidget):def __init__(self, title):super(MyWindow, self).__init__()self.setWindowTitl…

遵循开源软件安全路线图

毫无疑问&#xff0c;开源软件对于满足联邦任务所需的开发和创新至关重要&#xff0c;因此其安全性至关重要。 OSS&#xff08;运营支持系统&#xff09; 支持联邦政府内的每个关键基础设施部门。 联邦政府认识到这一点&#xff0c;并正在采取措施优先考虑 OSS 安全&#xff…

STM32_SPI总线驱动OLED详细原理讲解

目录 这里写目录标题 第13章 Cortex-M4-SPI总线13.1 SPI总线概述13.1.1 SPI总线介绍13.1.2 SPI总线接口与物理拓扑结构13.1.3 SPI总线通信原理13.1.4 SPI总线数据格式 13.2 IO口模拟SPI操作OLED13.2.1 常见的显示设备13.2.2 OLED显示屏概述13.2.3 OLED特征13.2.4 显示原理13.2.…

【Android】使用XML资源文件存储配置项:降低代码耦合性并提高可重用性

前言 在Android开发中&#xff0c;我们经常需要存储一些配置项。 例如在创建Retrofit实例时&#xff0c;需要指定baseUrl。如果需要修改替换整个项目中的baseUrl&#xff0c;那将会是一件很痛苦的事情。 为了方便管理和维护这些配置项&#xff0c;我们可以使用资源文件来存储…

无需API实现MySQL与巨量引擎的对接

通过数环通&#xff0c;您可以使用不到几分钟的时间即可实现MySQL与巨量引擎的对接与集成&#xff0c;从而高效实现工作流程自动化&#xff0c;降本增效&#xff01; 1.产品介绍 巨量引擎是字节跳动旗下的营销服务品牌&#xff0c;它整合了字节跳动旗下的产品及海量内容&#…