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

一、线程间通信的核心场景

最典型的场景是生产者 - 消费者模型

  • 生产者线程:生产数据(往共享容器里放数据)
  • 消费者线程:消费数据(从共享容器里取数据)
  • 通信需求:容器满时生产者等待,容器空时消费者等待;生产 / 消费后唤醒对方。

二、Java 实现线程通信的 3 种核心方式

方式 1:使用 Object 类的 wait ()/notify ()/notifyAll ()(基础经典)

这是基于对象监视器(锁)的通信方式,必须在synchronized代码块 / 方法中使用:

  • wait():让当前线程释放锁并进入等待状态,直到被唤醒。
  • notify():唤醒等待该对象锁的一个线程(随机)。
  • notifyAll():唤醒等待该对象锁的所有线程(推荐,避免线程永久等待)。

完整示例(生产者 - 消费者)

java

运行

// 共享资源:仓库(最多存1个产品) class Warehouse { private int product = 0; // 产品数量 // 生产产品(生产者调用) public synchronized void produce() { // 仓库已满,生产者等待 while (product >= 1) { // 用while而非if,防止虚假唤醒 try { wait(); // 释放锁,进入等待 } catch (InterruptedException e) { e.printStackTrace(); } } // 生产产品 product++; System.out.println(Thread.currentThread().getName() + " 生产了产品,当前库存:" + product); notifyAll(); // 唤醒消费者 } // 消费产品(消费者调用) public synchronized void consume() { // 仓库为空,消费者等待 while (product <= 0) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // 消费产品 product--; System.out.println(Thread.currentThread().getName() + " 消费了产品,当前库存:" + product); notifyAll(); // 唤醒生产者 } } // 生产者线程 class Producer implements Runnable { private Warehouse warehouse; public Producer(Warehouse warehouse) { this.warehouse = warehouse; } @Override public void run() { // 循环生产5次 for (int i = 0; i < 5; i++) { warehouse.produce(); try { Thread.sleep(500); // 模拟生产耗时 } catch (InterruptedException e) { e.printStackTrace(); } } } } // 消费者线程 class Consumer implements Runnable { private Warehouse warehouse; public Consumer(Warehouse warehouse) { this.warehouse = warehouse; } @Override public void run() { // 循环消费5次 for (int i = 0; i < 5; i++) { warehouse.consume(); try { Thread.sleep(800); // 模拟消费耗时 } catch (InterruptedException e) { e.printStackTrace(); } } } } // 测试类 public class WaitNotifyDemo { public static void main(String[] args) { Warehouse warehouse = new Warehouse(); // 启动生产者和消费者线程 new Thread(new Producer(warehouse), "生产者1").start(); new Thread(new Consumer(warehouse), "消费者1").start(); } }

关键解释

  1. wait()必须在synchronized块中调用,因为调用前需要先获取对象锁,调用后会释放锁(这是和sleep()的核心区别:sleep()不会释放锁)。
  2. while判断条件而非if:防止 “虚假唤醒”(线程被唤醒后,条件可能已经不满足,需要重新检查)。
  3. notifyAll()notify()更安全:避免只唤醒同类线程(比如生产者唤醒生产者)导致死锁。
方式 2:使用 Condition 接口(JUC 包,更灵活)

Condition是 Java 并发包(java.util.concurrent)提供的增强版等待 / 唤醒机制,基于Lock锁实现,相比wait()/notify()更灵活(可以创建多个 Condition,实现精准唤醒)。

完整示例

java

运行

import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; // 共享资源:仓库 class Warehouse2 { private int product = 0; private final Lock lock = new ReentrantLock(); // 可重入锁 private final Condition producerCondition = lock.newCondition(); // 生产者条件 private final Condition consumerCondition = lock.newCondition(); // 消费者条件 // 生产产品 public void produce() { lock.lock(); // 获取锁 try { while (product >= 1) { producerCondition.await(); // 生产者等待(替代wait()) } product++; System.out.println(Thread.currentThread().getName() + " 生产了产品,当前库存:" + product); consumerCondition.signal(); // 精准唤醒消费者(替代notify()) } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); // 释放锁(必须在finally中,防止异常导致锁不释放) } } // 消费产品 public void consume() { lock.lock(); try { while (product <= 0) { consumerCondition.await(); // 消费者等待 } product--; System.out.println(Thread.currentThread().getName() + " 消费了产品,当前库存:" + product); producerCondition.signal(); // 精准唤醒生产者 } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } // 测试类 public class ConditionDemo { public static void main(String[] args) { Warehouse2 warehouse = new Warehouse2(); new Thread(() -> { for (int i = 0; i < 5; i++) { warehouse.produce(); try { Thread.sleep(500); } catch (InterruptedException e) {} } }, "生产者1").start(); new Thread(() -> { for (int i = 0; i < 5; i++) { warehouse.consume(); try { Thread.sleep(800); } catch (InterruptedException e) {} } }, "消费者1").start(); } }

核心优势

  • 可以创建多个Condition对象,实现 “精准唤醒”(比如只唤醒生产者 / 消费者),而notify()是随机唤醒。
  • Lock锁的获取和释放更灵活(可以在非代码块中使用),且支持尝试获取锁(tryLock())。
方式 3:使用 BlockingQueue(阻塞队列,最高效)

BlockingQueue是 JUC 包提供的阻塞队列,内置了线程通信逻辑,无需手动写 wait/notify,是生产环境中最推荐的方式。

核心特性:

  • 队列满时,入队操作(put())会阻塞生产者线程。
  • 队列空时,出队操作(take())会阻塞消费者线程。

完整示例

java

运行

import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; // 测试类(无需自定义仓库,直接用BlockingQueue) public class BlockingQueueDemo { // 创建容量为1的阻塞队列(模拟仓库) private static final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(1); public static void main(String[] args) { // 生产者线程:往队列里放数据 new Thread(() -> { for (int i = 1; i <= 5; i++) { try { queue.put(i); // 队列满时阻塞 System.out.println(Thread.currentThread().getName() + " 生产了产品" + i + ",队列大小:" + queue.size()); Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }, "生产者1").start(); // 消费者线程:从队列里取数据 new Thread(() -> { for (int i = 1; i <= 5; i++) { try { Integer product = queue.take(); // 队列空时阻塞 System.out.println(Thread.currentThread().getName() + " 消费了产品" + product + ",队列大小:" + queue.size()); Thread.sleep(800); } catch (InterruptedException e) { e.printStackTrace(); } } }, "消费者1").start(); } }

输出效果

plaintext

生产者1 生产了产品1,队列大小:1 消费者1 消费了产品1,队列大小:0 生产者1 生产了产品2,队列大小:1 消费者1 消费了产品2,队列大小:0 ...(生产者和消费者交替执行)

核心优势

  • 无需手动处理锁和等待 / 唤醒,代码极简,不易出错。
  • 支持多种队列类型:ArrayBlockingQueue(数组实现)、LinkedBlockingQueue(链表实现)、SynchronousQueue(无容量队列)等。

三、核心方法对比

方式核心 API优点缺点
wait()/notify()Object 类方法基础经典,无需额外依赖只能随机唤醒,需手动处理锁,易出错
ConditionLock+Condition精准唤醒,锁更灵活代码稍复杂,需手动释放锁
BlockingQueueput()/take()极简高效,生产环境首选依赖 JUC 包,灵活性稍低(适合标准生产消费场景)

总结

  1. 线程间通信的核心是共享资源 + 等待 / 唤醒,目的是让线程协同工作而非抢占资源。
  2. 入门学习用wait()/notify()理解原理,进阶用Condition实现精准控制,生产环境优先用BlockingQueue(极简且不易出错)。
  3. 关键注意点:wait()会释放锁,sleep()不会;必须在锁保护的代码块中使用等待 / 唤醒方法;用while判断条件防止虚假唤醒。

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

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

相关文章

AI 写论文哪个软件最好?实测封神!虎贲等考 AI 凭硬核实力领跑全场

毕业季的论文战场硝烟四起&#xff0c;“AI 写论文哪个软件最好” 的灵魂拷问&#xff0c;成了无数学生的每日必问。有人踩坑 “虚构文献生成器”&#xff0c;查重率居高不下&#xff1b;有人被 “AI 痕迹检测” 难住&#xff0c;辛苦写的论文被判违规&#xff1b;还有人在多个…

Conda 常用命令整理

环境管理 管理独立的 Python 运行环境,解决项目间依赖冲突。创建环境 # 创建名为 myenv 的新环境 conda create -n myenv# 创建并指定 Python 版本 conda create -n myenv python=3.9激活/切换环境 # 进入 myenv 环境…

AI 写论文哪个软件最好?实测虎贲等考 AI:毕业论文的智能通关王炸

毕业季的论文赛道上&#xff0c;“AI 写论文哪个软件最好” 的灵魂拷问&#xff0c;总能在高校互助群里刷屏。有人踩坑通用 AI 的 “文献幻觉”&#xff0c;有人栽在单一工具的 “功能割裂”&#xff0c;还有人被查重和 AIGC 检测的双重门槛难住。作为深耕论文写作科普的测评博…

6.4 Cross-Attention机制:视觉与语言如何深度融合

6.4 Cross-Attention机制:视觉与语言如何深度融合 引言 在前三节中,我们学习了视觉问答(VQA)、视觉定位(Grounding)以及DETR和GLIP等新一代目标检测技术。这些技术的核心都依赖于一个关键机制——跨模态注意力(Cross-Attention),它使得视觉和语言模态能够进行深层次…

spring传播机制事务相关

spring传播机制事务相关一、REQUIRED 核心规则(一句话记住) 有则加入,无则新建 完整严谨描述:当一个被 @Transactional 标记的目标方法执行时,先检查当前执行环境是否已经存在事务; 如果当前已有事务 → 该方法不…

别墅装修怎么选入户门?2025-2026别墅入户门选购终极指南:十大品牌权威排名揭晓 - 匠子网络

body { font-family: "Microsoft YaHei", sans-serif; line-height: 1.6; color: rgba(51, 51, 51, 1); max-width: 1200px; margin: 0 auto; padding: 20px } h1 { text-align: center; color: rgba(139, 6…

7.1 NL2SQL核心技术:让AI听懂你的自然语言查询

7.1 NL2SQL核心技术:让AI听懂你的自然语言查询 在人工智能时代,让计算机理解人类的自然语言并执行相应的操作一直是我们的终极目标之一。其中,将自然语言转换为SQL查询(NL2SQL)是一项非常重要的任务,它能够使非技术人员通过简单的自然语言指令来查询数据库,而无需掌握复…

有人吃NMN像换了个人,有人却没啥变化!盼生派带你搞懂NMN真相 - 速递信息

42岁的李女士没有任凭岁月摆布,没有断崖衰老,没有被人猜错年龄,她心里都很得意。这得益她改变了思路,才彻底告别了“抗衰焦虑”。曾经靠浓妆遮盖的法令纹变浅了,熬夜后第二天也不会昏沉乏力,就连体检报告上的各项…

AI 写论文哪个软件最好?实测虎贲等考 AI:毕业论文的智能通关密码

毕业季的论文战场&#xff0c;“AI 写论文哪个软件最好” 的灵魂拷问&#xff0c;总能在各大高校的互助群里刷屏。不少同学踩坑无数&#xff1a;有的工具生成内容空洞无物&#xff0c;有的文献引用漏洞百出&#xff0c;有的查重结果与学校标准脱节。作为深耕论文写作科普的测评…

云数潮:每天三分钟,让普通人参与数字经济 - 速递信息

在数字经济成为时代发展重要方向的当下,真正的关键不在于技术本身,而在于——普通人是否真正拥有可执行的参与入口。 如果只有概念而缺乏可行路径,数字经济终究难以实现普惠。 云数潮(YunData Wave),正是在这一背…

虎贲等考 AI:重塑学术写作范式的智能全流程解决方案

在学术研究数字化转型的浪潮下&#xff0c;论文写作不再是孤军奋战的苦旅。虎贲等考 AI 智能写作平台—— 一款深度融合人工智能技术的专业论文写作辅助工具&#xff0c;以 “真实赋能、智能高效、合规严谨” 为核心定位&#xff0c;构建起从开题构思到答辩定稿的全链条学术服务…

毕业生必看:论文AI率太高被退回?5招搞定降AI全攻略 - 还在做实验的师兄

论文AI率太高被导师打回来?别慌。这篇攻略教你5招搞定:先搞清楚检测原理,再用手动+工具组合拳处理。核心推荐嘎嘎降AI(达标率99.26%)和比话降AI(知网专攻),能把AI率从70%+降到10%以下。毕业生必看:论文AI率太…

bind接口的address详解

QUdpSocket::bind() 接口中的 address 参数&#xff08;类型为 QHostAddress&#xff09;用于指定 本地 哪个网络接口&#xff08;IP 地址&#xff09;来监听 UDP 数据报。这个参数对 socket 的行为有决定性影响&#xff0c;下面从原理、常用值、使用场景和注意事项四个方面详细…

Kimi写的内容AI率太高?这几款工具帮你降到10%以下 - 还在做实验的师兄

Kimi支持超长文本输入,写文献综述很方便,但生成内容AI率普遍在70%-85%。Kimi自己改只能降到30%-40%,而且容易改偏原意。要想降到10%以下,必须用专业降AI工具:嘎嘎降AI(性价比高)、比话降AI(效果稳定)最靠谱。…

端口的本质是什么

端口&#xff08;Port&#xff09;的本质是操作系统用于区分同一台主机上不同网络通信进程或服务的逻辑标识符。它不是物理设备&#xff0c;而是一个 16 位的整数&#xff08;0~65535&#xff09;&#xff0c;与 IP 地址结合使用&#xff0c;构成“套接字地址&#xff08;Socke…

聊聊2026年果汁生产线资深厂商,上望机械制造靠谱吗? - 工业品牌热点

2026年饮料行业消费升级加速,健康化、个性化需求驱动果汁市场规模持续扩容,高效果汁生产线已成为企业提升产能效率、保障产品品质、抢占市场份额的核心载体。无论是中小微饮料厂的初创建厂需求,还是成熟品牌的产能升…

Kimi降AI效果怎么样?月之暗面AI助手降论文AI率实测 - 还在做实验的师兄

Kimi作为月之暗面出品的AI助手,长文本处理能力强,但用它降AI效果有限。实测反复改写3轮,AI率从82%只能降到65%左右。想真正把AI率降到学校要求的20%以下,还是需要专业工具:嘎嘎降AI(4.8元,达标率99.26%)或比话…

告别绘图加班!虎贲等考 AI 科研绘图:让数据秒变期刊级高颜值图表

还在为科研绘图熬秃脑袋&#xff1f;用 Origin 调试参数两小时&#xff0c;图表排版依旧混乱&#xff1b;用 Excel 画不出复杂热图&#xff0c;数据可视化效果大打折扣&#xff1b;好不容易用 Visio 画出实验装置图&#xff0c;却因不符合期刊规范被打回重改…… 在科研圈&…

数值方法验证: 制造解方法(Method of Manufactured Solutions,MMS)介绍

文章目录一、基本思想二、实施步骤&#xff08;以一个通用 PDE 为例&#xff09;三、优点四、注意事项五、经典文献推荐六、实践建议Method of Manufactured Solutions&#xff08;MMS&#xff0c;制造解方法&#xff09; 是一种广泛用于验证偏微分方程&#xff08;PDE&#xf…

10 分钟搞定学术 PPT!虎贲等考 AI PPT:逻辑与颜值双在线的汇报神器

还在为开题答辩 PPT 熬到凌晨三点&#xff1f;辛辛苦苦写的论文&#xff0c;做成 PPT 却逻辑混乱、排版拉垮&#xff0c;被导师批 “抓不住重点”&#xff1f;作为深耕论文写作科普的博主&#xff0c;我发现 90% 的学术人做 PPT&#xff0c;都困在 “内容提炼难、格式调整烦、风…