【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;
	}

	@Override
	public 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;
	}

	@Override
	public 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类中。


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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

求10的阶乘之和

这个问题很简单&#xff0c;我们用for循环就可以做到&#xff01; 目录 1.用两个for循环求值 2.用一个for循环求值 1.用两个for循环求值 int main() {int i 1;int ret 1;int sum 0;int n 0;for (n 1; n < 10; n){ret 1;for (i 1; i < n; i){ret ret * i;}sum …

文件传输客户端 SecureFX mac中文版支持多种协议

SecureFX mac是一款功能强大的文件传输客户端&#xff0c;可在 Mac 操作系统上使用。它由 VanDyke Software 公司开发&#xff0c;旨在为用户提供安全、可靠、高效的文件传输服务。 SecureFX 支持多种协议&#xff0c;包括 SFTP、SCP、FTP、FTP over SSL/TLS 和 HTTP/S。它使用…

Django 配置 Email Admin 详细指南

概要 Django 是一个高级的 Python Web 框架&#xff0c;它鼓励快速开发和清洁、实用的设计。当你正在开发一个 Django 项目时&#xff0c;监控网站的运行情况是非常必要的。Django 提供了一个功能强大的 admin 界面&#xff0c;但同时也可以通过配置 email admin 来获取网站的…

第9章 K8s进阶篇-持久化存储入门

9.1 k8s存储Volumes介绍 Container&#xff08;容器&#xff09;中的磁盘文件是短暂的&#xff0c;当容器崩溃时&#xff0c;kubelet会重新启动容器&#xff0c;但最初的文件将丢失&#xff0c;Container会以最干净的状态启动。另外&#xff0c;当一个Pod运行多个Container时&…

设计模式解码:软件工程架构的航标

引言 软件工程领域的设计模式&#xff0c;就像是建筑师手中的设计蓝图&#xff0c;它们是经验的总结&#xff0c;指导开发者如何在面对层出不穷的编程难题时&#xff0c;构建出既稳固又灵活的软件结构。就像一座经过精心设计的大厦能够经受住风雨的考验一样&#xff0c;一个利用…

MAC地址注册的网络安全影响和措施分析

MAC地址注册对网络安全具有重要影响&#xff0c;同时也需要采取相应的措施来应对潜在的安全风险。以下是有关MAC地址注册的网络安全影响和应对措施的分析&#xff1a; 影响&#xff1a; 1. 身份验证&#xff1a;MAC地址注册可用于设备的身份验证&#xff0c;但MAC地址本身并不…

MATLAB 机械臂逆运动学进行轨迹控制建模

系列文章目录 文章目录 系列文章目录前言一、模型概览1.1 Target Pose Generation 目标姿势生成1.2 Inverse Kinematics 逆运动学1.3 Manipulator Dynamics 机械手动力学1.4 Pose Measurement 姿势测量 二、机械手定义三、生成航点四、模型设置五、模拟机械手运动六、将结果可视…

how to find gcc openbug

https://gcc.gnu.org/bugzilla/query.cgi?formatadvanced

“开源 vs. 闭源:大模型的未来发展趋势预测“——探讨大模型未来的发展方向

文章目录 每日一句正能量前言什么是大模型的开源与闭源开源与闭源的定义和特点开源的意义开源和闭源的优劣势比较不同的大模型企业&#xff0c;开源、闭源的策略不尽相同。开源vs 闭源&#xff1a;两者并非选择题后记 每日一句正能量 依赖别人的人等于折断了自己的翅膀&#xf…

SQL中的数据类型和规范化,助力数据存储优化

大家好&#xff0c;目前优化数据存储对于获得良好的性能始终至关重要&#xff0c;选择合适的数据类型并应用正确的规范化过程对于决定其性能至关重要。本文将介绍最重要和最常用的数据类型和规范化过程。 一、SQL中的数据类型 SQL中主要有两种数据类型&#xff1a;字符串和数…

【文献阅读】Self similarity driven color demosaicking

[PDF][Code] 1. 摘要 每个像素只测量一种颜色成分&#xff0c;红色、绿色或蓝色&#xff0c;人们可以在每个像素推断出整个颜色信息。这种推断需要深刻理解颜色之间的相互作用&#xff0c;以及图像局部几何的参与。虽然在以非常小的相对误差进行这种推断方面非常成功&#xff…

深入C++ Vector:解密vector的奥秘与底层模拟实现揭秘

W...Y的主页 &#x1f60a; 代码仓库分享 &#x1f495; &#x1f354;前言&#xff1a; 我们学习了STL中的string以及其所有重要接口并进行了模拟实现&#xff0c;但是STL中包含的内容不止于此。学习了string之后继续学习STL中的vector&#xff0c;学习成本会大大降低&#…

Notepad++ 和正则表达式 只保留自己想要的内容

一、需求 如下文本&#xff0c;三段相同结构的数据&#xff0c;想要获取每段结构中‘重复的Ids ’后面的数字 2023-10-26 18:49:49 重复的Ids 26443,26575 要删除的Ids 4174,4199,4200,55502023-10-26 18:49:49 重复的Ids 26436,26443,26575 要删除的Ids 4166,4199,4200,5550…

Docker(镜像、容器、仓库)工具安装使用命令行选项及构建、共享和运行容器化应用程序

文章目录 前言&#x1f31f;一、Docker工具安装&#x1f31f;二、Docker命令行选项&#x1f30f;2.1.docker run命令选项&#xff1a;&#x1f30f;2.2.docker build命令选项&#xff1a;&#x1f30f;2.3.docker images命令选项&#xff1a;&#x1f30f;2.4.docker ps命令选项…

实用技巧:在C和cURL中设置代理服务器爬取www.ifeng.com视频

概述&#xff1a; 网络爬虫技术作为一种自动获取互联网数据的方法&#xff0c;在搜索引擎、数据分析、网站监测等领域发挥着重要作用。然而&#xff0c;面对反爬虫机制、网络阻塞、IP封禁等挑战&#xff0c;设置代理服务器成为解决方案之一。代理服务器能够隐藏爬虫的真实IP地…

MySQL JDBC编程

MySQL JDBC编程 文章目录 MySQL JDBC编程1. 数据库编程的必备条件2. Java的数据库编程&#xff1a;JDBC3. JDBC工作原理4. JDBC使用5. JDBC常用接口和类5.1 JDBC API5.2 数据库连接Connection5.3 Statement对象5.4 ResultSet对象 1. 数据库编程的必备条件 编程语言&#xff1a;…

web:[BUUCTF 2018]Online Tool

题目 打开页面显示如下&#xff0c;进行代码审计 上述代码主要功能是接收‘host’参数&#xff0c;后使用nmap扫描主机端口 首先检查是否存在HTTP_X_FORWARDED_FOR头&#xff0c;若存在&#xff0c;将值赋值给EMOTE_ADDR,是为了跟踪用户真实的IP地址 后用检查get‘host’是否…

第十九章,Java绘图

Graphics类 Graphics类是所有图形上下文的抽象基本类&#xff0c;它允许应用程序在组件以及闭屏图像上进行绘制 Graphics类封装了Java支持的基本绘图操作所需的状态信息&#xff0c;主要包括颜色、字体、画笔、文本、图像等 Graphics类提供了常用的绘图方法&#xff0c;利用这些…

Ubuntu 18.04无网络连接的n种可能办法

文章目录 网络图标消失&#xff0c;Ubuntu无网络连接VMware上Ubuntu18.04&#xff0c;桥接了多个网卡&#xff0c;其中一个用来上网&#xff0c;均设置为静态ip网络桥接链路没有接对路由不对 网络图标消失&#xff0c;Ubuntu无网络连接 sudo service network-manager stop sud…

家庭网络中的组网方式

家庭网络中&#xff0c;目前也衍生出了比较多的组网方式&#xff0c;也不是只有Easymesh&#xff0c;我们还是要辩证的去看&#xff0c;没有绝对的好和坏&#xff0c;需求不同&#xff0c;取舍不同。 这里博主简单的介绍几种组网方式&#xff0c;上图也比较直观 1.wds wds是…