Java是如何实现线程间通信的?

在Java中,线程间通信可以通过以下方式实现:

1.共享变量

线程可以通过共享的变量进行通信。多个线程可以读写同一个变量来交换信息。在这种情况下,需要确保线程对共享变量的访问是同步的,以避免数据竞争和不一致的结果。

以下是一个使用共享变量进行线程通信的示例代码:

class Message {private String content;private boolean hasNewMessage = false;public synchronized void putMessage(String content) {while (hasNewMessage) {try {wait(); // 等待直到消息被消费} catch (InterruptedException e) {Thread.currentThread().interrupt();}}this.content = content;hasNewMessage = true;notifyAll(); // 唤醒等待的线程}public synchronized String getMessage() {while (!hasNewMessage) {try {wait(); // 等待直到有新消息} catch (InterruptedException e) {Thread.currentThread().interrupt();}}hasNewMessage = false;notifyAll(); // 唤醒等待的线程return content;}
}class Producer implements Runnable {private Message message;public Producer(Message message) {this.message = message;}public void run() {String[] messages = { "Hello", "World", "Goodbye" };for (String msg : messages) {message.putMessage(msg);System.out.println("Producer: " + msg);try {Thread.sleep(1000); // 模拟耗时操作} catch (InterruptedException e) {Thread.currentThread().interrupt();}}message.putMessage("Done");}
}class Consumer implements Runnable {private Message message;public Consumer(Message message) {this.message = message;}public void run() {String msg = "";while (!msg.equals("Done")) {msg = message.getMessage();System.out.println("Consumer: " + msg);}}
}public class Main {public static void main(String[] args) {Message message = new Message();Thread producerThread = new Thread(new Producer(message));Thread consumerThread = new Thread(new Consumer(message));producerThread.start();consumerThread.start();}
}

在这个示例中,有一个Message类,它表示一个消息对象。Message类中的putMessage方法用于生产消息,并将消息存储在content变量中。getMessage方法用于消费消息,并返回存储的消息内容。这两个方法都使用synchronized关键字来实现同步,以确保线程安全。

有一个Producer类,它实现了Runnable接口,用于在一个线程中生产消息。Consumer类也实现了Runnable接口,用于在另一个线程中消费消息。

在Main类的main方法中,创建了一个Message对象,并创建了一个生产者线程和一个消费者线程。通过调用start方法启动这两个线程,它们将并发地生产和消费消息。

在控制台输出中,我们将看到生产者线程和消费者线程交替输出消息,它们通过共享的Message对象进行通信。

2.等待/通知机制

Java提供了wait、notify和notifyAll方法,用于线程间的等待和通知。线程可以调用wait方法暂停自己的执行,直到另一个线程调用相同对象上的notify或notifyAll方法来唤醒它们。

以下是一个使用等待/通知机制进行线程通信的示例代码:

class Message {private String content;private boolean hasNewMessage = false;public synchronized void putMessage(String content) {while (hasNewMessage) {try {wait(); // 等待直到消息被消费} catch (InterruptedException e) {Thread.currentThread().interrupt();}}this.content = content;hasNewMessage = true;notifyAll(); // 唤醒等待的线程}public synchronized String getMessage() {while (!hasNewMessage) {try {wait(); // 等待直到有新消息} catch (InterruptedException e) {Thread.currentThread().interrupt();}}hasNewMessage = false;notifyAll(); // 唤醒等待的线程return content;}
}class Producer implements Runnable {private Message message;public Producer(Message message) {this.message = message;}public void run() {String[] messages = { "Hello", "World", "Goodbye" };for (String msg : messages) {message.putMessage(msg);System.out.println("Producer: " + msg);try {Thread.sleep(1000); // 模拟耗时操作} catch (InterruptedException e) {Thread.currentThread().interrupt();}}message.putMessage("Done");}
}class Consumer implements Runnable {private Message message;public Consumer(Message message) {this.message = message;}public void run() {String msg = "";while (!msg.equals("Done")) {msg = message.getMessage();System.out.println("Consumer: " + msg);}}
}public class Main {public static void main(String[] args) {Message message = new Message();Thread producerThread = new Thread(new Producer(message));Thread consumerThread = new Thread(new Consumer(message));producerThread.start();consumerThread.start();}
}

这个示例中的代码与之前的示例相同。不同之处在于,putMessage和getMessage方法使用了wait和notifyAll方法来进行线程间的等待和通知。当putMessage方法调用wait时,它会释放对象的锁并等待被唤醒。当getMessage方法调用notifyAll时,它会唤醒等待的线程并重新获得对象的锁。

通过这种方式,生产者线程在没有新消息时等待,直到消费者线程消费了消息并调用notifyAll方法。同样,消费者线程在没有新消息时等待,直到生产者线程产生新消息并调用notifyAll方法。

无论是共享变量还是等待/通知机制,Java提供了多种方法来实现线程间的通信。选择适当的方法取决于特定的应用场景和需求。

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

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

相关文章

spring service事务传播

spring定义的事务行为有以下几种: REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。 MANDATORY--支持当前事务&#xff…

LabVIEW开发感应电机在线匝间短路故障诊断系统

LabVIEW开发感应电机在线匝间短路故障诊断系统 工业中使用的超过85%的电动机是三相感应电动机。它们因其可靠性、设计便利性、高性能和过载能力而被广泛用于不同的应用,例如制造、加工、电力系统、运输等。无论它们的能力如何,它们都被认为是现代工业学…

Unity通过偏移UV播放序列帧动画

大家好,我是阿赵。   在Unity引擎里面用shader播放序列图,估计很多人都有用到了,我自己而已写过好几个版本。这里大概介绍一下。 一、原理 先说目的,我现在有一张这样的图片: 这张图片上面,有9个格子&a…

使用errors.Wrapf()代替log.Error()

介绍不同语言的错误处理机制: Error handling patterns[1] Musings about error handling mechanisms in programming languages[2] 项目中 main调func1,func1调取func2... 这样就会出现很多的 if err ! nil { log.Printf()} , 在Kibana上查看时会搜到多条日志, 需要…

架构师成长之路|Redis key过期清除策略

Eviction policies maxmemory 100mb 当我们设置的内存达到指定的内存量时,清除策略的配置方式决定了默认行为。Redis可以为可能导致使用更多内存的命令返回错误,也可以在每次添加新数据时清除一些旧数据以返回到指定的限制。 当达到最大内存限制时,Redis所遵循的确切行为是…

美妆+七人拼团模式:如何打造新型社交电商营销方式

美妆是一个充满竞争和创新的行业,要想在市场上获得优势,就需要不断寻找新的营销方式,吸引和留住消费者。七人拼团模式就是一种结合了社交电商和拼购玩法的新型商业模式,它可以利用社交网络的裂变效应,增加品牌曝光度和…

vue+elementUI el-select 自定义搜索逻辑(filter-method)

下拉列表的默认搜索是搜索label显示label,我司要求输入id显示label名称 <el-form-item label"部门&#xff1a;"><el-select v-model"form.region1" placeholder"请选择部门" filterable clearable:filter-method"dataFilter&qu…

《Go 语言第一课》课程学习笔记(十五)

并发 Go 的并发方案&#xff1a;goroutine 并行&#xff08;parallelism&#xff09;&#xff0c;指的就是在同一时刻&#xff0c;有两个或两个以上的任务&#xff08;这里指进程&#xff09;的代码在处理器上执行。 并发不是并行&#xff0c;并发关乎结构&#xff0c;并行关…

Playwright for Python:基础用法

写在前面 Playwright for Python&#xff1a;安装及初步使用 自动化交流 Playwright可以与HTML输入元素进行交互&#xff0c;例如文本输入框、复选框、单选按钮、下拉选项等。它可以模拟鼠标点击、输入字符、按键和快捷键&#xff0c;还可以上传文件并将焦点设置到元素上。 …

AndroidTV端:酒店扫码认证投屏DLNA

被老板叼了几次了&#xff0c;最近实在忍不了&#xff0c;准备离职&#xff1b; 但是担心离职后长时间没有办法找到工作 就想贡献一套平时琢磨出来的程序&#xff0c;请各位有能力的话带我熬过这凛冽的寒冬。 目前写出来的&#xff0c;有三个端&#xff1a;安卓TV端&#xf…

准备HarmonyOS开发环境

引言 在开始 HarmonyOS 开发之前&#xff0c;需要准备好开发环境。本章将详细指导你如何安装 HarmonyOS SDK、配置开发环境、创建 HarmonyOS 项目。 目录 安装 HarmonyOS SDK 配置开发环境 创建 HarmonyOS 项目 总结 1. 安装 HarmonyOS SDK HarmonyOS SDK 是开发 Harmo…

uni-app 之 scroll-view和swiper

uni-app 之 scroll-view和swiper <!-- vue2的<template>里必须要有一个盒子&#xff0c;不能有两个&#xff0c;这里的盒子就是 view--> <template><view><navigator url"/pages/home/home"><button style"background: #ff00f…

【Selenium2+python】自动化unittest生成测试报告

前言 批量执行完用例后&#xff0c;生成的测试报告是文本形式的&#xff0c;不够直观&#xff0c;为了更好的展示测试报告&#xff0c;最好是生成HTML格式的。 unittest里面是不能生成html格式报告的&#xff0c;需要导入一个第三方的模块&#xff1a;HTMLTestRunner 一、导…

leetcode1288. 删除被覆盖区间(java)

删除被覆盖区间 题目描述贪心法代码演示 题目描述 难度 - 中等 leetcode1288. 删除被覆盖区间 给你一个区间列表&#xff0c;请你删除列表中被其他区间所覆盖的区间。 只有当 c < a 且 b < d 时&#xff0c;我们才认为区间 [a,b) 被区间 [c,d) 覆盖。 在完成所有删除操作…

MySql学习笔记05——DML

DML 插入数据insert insert into 表名(字段名1&#xff0c;字段名2&#xff0c;字段名3...)values(值1&#xff0c;值2&#xff0c;值3)&#xff1b;字段名和值要一一对应&#xff08;顺序对应&#xff0c;数据类型对应&#xff09; insert into t_student(no,name,sex,age,…

Docker使用数据卷挂载进行数据存储与共享

一、挂载和数据卷 在 Docker 中&#xff0c;挂载&#xff08;Mounting&#xff09;和数据卷&#xff08;Data Volumes&#xff09;是用于在容器和宿主机之间共享数据的机制。 挂载&#xff1a;将宿主机文件系统中的目录或文件与容器中的目录或文件进行关联的过程。数据卷&…

收入下降,亏损扩大,利润率急剧恶化,蔚来仍充满风险

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 蔚来第二季度财报分析 猛兽财经从蔚来&#xff08;NIO&#xff09;2023年第二季度财报中&#xff0c;获得的最大收获并不是该公司的收入下降或亏损扩大&#xff0c;而是由于价格竞争加剧&#xff0c;中国电动汽车行业整体上…

什么是安全运营中心(SOC),应该了解什么

安全运营中心&#xff08;SOC&#xff09; 是一种企业监视和警报设施&#xff0c;可帮助组织检测安全威胁、监视安全事件和分析性能数据以改进公司运营。 什么是安全运营中心&#xff08;SOC&#xff09; 安全运营中心&#xff08;SOC&#xff09;是一个中央监视和监视中心&a…

第二次作业

1.编写脚本for1.sh,使用for循环创建20账户&#xff0c;账户名前缀由用户从键盘输入&#xff0c;账户初始密码由用户输入&#xff0c;例如: test1、test2、test3、.....、 test10 编写脚本for1.sh 执行脚本&#xff1a;bash for.sh 2&#xff0c;编写脚本for2.sh,使用for循环,通…

springboot 集成 lucene

简介 数据每分钟产生200条&#xff0c;使用mysql储存。目前有数据超过700M。按照日期查询&#xff0c;按月查询包含每次超过20w条以上&#xff0c;时间比较长。计划使用lucene优化查询&#xff0c;不适用es是因为项目较小&#xff0c;没有更富裕的资源。 基本步骤 引入依赖。…