news 2026/2/28 8:48:02

线程间通信的秘密:如何让B感知A的变化?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
线程间通信的秘密:如何让B感知A的变化?

文章目录

  • 线程间通信的秘密:如何让B感知A的变化?
    • 一、引言:为什么线程间通信这么重要?
    • 二、最简单的“通信”方式:共享变量
      • 示例代码:
      • 分析:
    • 三、解决可见性问题:volatile关键字
      • 修改后的代码:
      • 分析:
    • 四、高级的通信机制:wait和notify
      • 示例代码:
      • 分析:
    • 五、生产者-消费者模式
      • 示例代码:
      • 分析:
    • 六、总结
    • 希望这篇总结能帮助你更好地理解线程间通信的各种方法!
      • 📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

线程间通信的秘密:如何让B感知A的变化?

大家好!我是闫工,今天咱们要聊一个看似简单但其实非常重要的问题——线程间通信。这个问题在多线程编程中几乎无处不在,尤其是在并发场景下,如何让线程B感知到线程A的状态变化,是一个必须要解决的问题。

可能有的同学会觉得:“不就是线程之间共享变量吗?直接用一个全局变量不就行了?”但事实并非如此简单。线程间通信不仅仅是简单的数据共享,还需要考虑线程安全、内存可见性等问题。今天,咱们就从这个问题入手,一步步深入探讨如何让线程B感知到线程A的变化。


一、引言:为什么线程间通信这么重要?

在Java中,多线程编程的核心目标之一就是提高程序的执行效率。多个线程可以同时执行不同的任务,从而充分利用 CPU 的资源。然而,在实际开发中,线程之间往往需要协作,比如一个线程完成某个计算后,另一个线程才能继续处理结果。

举个简单的例子:假设线程A负责从数据库读取数据,线程B负责对这些数据进行处理。如果线程A没有读完数据,线程B就开始处理,那就会出问题。因此,我们需要一种机制,让线程B知道线程A已经完成了任务。

这就是线程间通信的核心——如何通知其他线程自己状态的变化。接下来,咱们就从简单到复杂,一步步探讨这个问题的解决方法。


二、最简单的“通信”方式:共享变量

在Java中,线程之间可以通过共享变量来进行通信。比如,可以定义一个全局变量flag,当线程A完成任务后,将flag设置为true,然后线程B就可以通过检查这个flag来判断是否可以继续执行。

示例代码:

publicclassSharedVariableExample{// 共享变量privatestaticbooleanflag=false;publicstaticvoidmain(String[]args){ThreadthreadA=newThread(()->{try{System.out.println("线程A开始工作...");Thread.sleep(2000);// 模拟耗时操作flag=true;System.out.println("线程A完成任务,flag设置为true");}catch(InterruptedExceptione){e.printStackTrace();}});ThreadthreadB=newThread(()->{while(!flag){// 等待线程A完成任务System.out.println("线程B在等待...");try{Thread.sleep(500);}catch(InterruptedExceptione){e.printStackTrace();}}System.out.println("线程B感知到变化,开始处理...");});threadA.start();threadB.start();}}

分析:

  1. 共享变量flag是一个全局变量,两个线程都可以访问它。
  2. 线程A的任务:完成耗时操作后,设置flagtrue
  3. 线程B的任务:循环检查flag,直到flag变为true

这种方法看起来简单,但在实际应用中存在一个大问题——不可见性。由于Java的内存模型允许多个线程有自己的缓存副本,如果线程A修改了flag,线程B可能看不到这个变化,从而导致死循环或其他异常行为。


三、解决可见性问题:volatile关键字

为了保证共享变量的变化对其他线程可见,我们可以使用volatile关键字。volatile告诉JVM,这个变量不会被缓存,每次读取时都会从主内存中获取最新的值。

修改后的代码:

publicclassVolatileExample{privatestaticvolatilebooleanflag=false;publicstaticvoidmain(String[]args){ThreadthreadA=newThread(()->{try{System.out.println("线程A开始工作...");Thread.sleep(2000);// 模拟耗时操作flag=true;System.out.println("线程A完成任务,flag设置为true");}catch(InterruptedExceptione){e.printStackTrace();}});ThreadthreadB=newThread(()->{while(!flag){// 等待线程A完成任务System.out.println("线程B在等待...");try{Thread.sleep(500);}catch(InterruptedExceptione){e.printStackTrace();}}System.out.println("线程B感知到变化,开始处理...");});threadA.start();threadB.start();}}

分析:

  1. volatile关键字:通过volatile修饰flag,确保了每个线程都能看到最新的值。
  2. 优点:简单、高效。
  3. 缺点:仅适用于简单的共享变量,无法处理更复杂的通信需求。

四、高级的通信机制:wait和notify

在Java中,Object类提供了wait()notify()方法,用于线程间的同步。这两个方法通常与synchronized关键字结合使用,可以实现生产者-消费者模式。

示例代码:

publicclassWaitNotifyExample{privatestaticfinalObjectlock=newObject();privatestaticbooleanflag=false;publicstaticvoidmain(String[]args){ThreadthreadA=newThread(()->{try{System.out.println("线程A开始工作...");Thread.sleep(2000);// 模拟耗时操作synchronized(lock){flag=true;lock.notify();// 通知其他线程System.out.println("线程A完成任务,flag设置为true");}}catch(InterruptedExceptione){e.printStackTrace();}});ThreadthreadB=newThread(()->{synchronized(lock){while(!flag){try{System.out.println("线程B在等待...");lock.wait();// 等待通知}catch(InterruptedExceptione){e.printStackTrace();}}System.out.println("线程B感知到变化,开始处理...");}});threadA.start();threadB.start();}}

分析:

  1. synchronized关键字:用于同步代码块,保证同一时间只有一个线程可以执行。
  2. wait()方法:让当前线程进入等待状态,并释放锁。
  3. notify()方法:唤醒一个正在等待的线程。
  4. 优点:支持更复杂的通信逻辑,且能避免“忙等待”(即不断轮询)的问题。
  5. 缺点:代码相对复杂,需要手动管理锁。

五、生产者-消费者模式

生产者-消费者模式是线程间通信的一个典型应用场景。一个线程负责生产数据(生产者),另一个线程负责消费数据(消费者)。当数据准备好后,生产者通知消费者可以开始处理。

示例代码:

importjava.util.Queue;importjava.util.concurrent.ConcurrentLinkedQueue;publicclassProducerConsumerExample{privatestaticQueue<Integer>queue=newConcurrentLinkedQueue<>();privatestaticfinalObjectlock=newObject();privatestaticbooleandone=false;publicstaticvoidmain(String[]args){Threadproducer=newThread(()->{try{System.out.println("生产者开始工作...");Thread.sleep(2000);// 模拟生产时间queue.add(123);synchronized(lock){done=true;lock.notify();System.out.println("生产者完成,数据已放入队列");}}catch(InterruptedExceptione){e.printStackTrace();}});Threadconsumer=newThread(()->{synchronized(lock){while(!done){try{System.out.println("消费者在等待...");lock.wait();}catch(InterruptedExceptione){e.printStackTrace();}}intdata=queue.poll();System.out.println("消费者获取数据:"+data);}});producer.start();consumer.start();}}

分析:

  1. 生产者:将数据放入队列后,设置donetrue并通知消费者。
  2. 消费者:等待直到done变为true,然后从队列中获取数据。
  3. 优点:支持高并发场景,代码结构清晰。

六、总结

  • 如果只需要简单的共享变量同步,可以使用volatile关键字。
  • 对于更复杂的通信需求,推荐使用wait()notify()方法,或者直接采用生产者-消费者模式。
  • 在实际开发中,还可以考虑使用Java并发包中的高级工具类(如CountDownLatchCyclicBarrier等),以简化代码逻辑。

希望这篇总结能帮助你更好地理解线程间通信的各种方法!

📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

成体系的面试题,无论你是大佬还是小白,都需要一套JAVA体系的面试题,我已经上岸了!你也想上岸吗?

闫工精心准备了程序准备面试?想系统提升技术实力?闫工精心整理了1000+ 套涵盖前端、后端、算法、数据库、操作系统、网络、设计模式等方向的面试真题 + 详细解析,并附赠高频考点总结、简历模板、面经合集等实用资料!

✅ 覆盖大厂高频题型
✅ 按知识点分类,查漏补缺超方便
✅ 持续更新,助你拿下心仪 Offer!

📥免费领取👉 点击这里获取资料

已帮助数千位开发者成功上岸,下一个就是你!✨

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/8 16:03:11

文献综述智能生成:让百考通AI为你的论文打造坚实理论基础

毕业论文写作是许多高校学子必须经历的一道关卡。据统计&#xff0c;超过70%的毕业生在论文写作过程中会遇到“学术写作障碍期”&#xff0c;而文献综述环节往往是最大的挑战之一。传统的手工文献梳理方式耗时耗力&#xff0c;且容易遗漏重要研究。那么&#xff0c;有没有更高效…

作者头像 李华
网站建设 2026/2/24 0:56:49

vivado2022.2安装教程与工业HMI集成的完整示例

Vivado 2022.2 安装与 Zynq 构建工业 HMI 的实战指南 从零开始&#xff1a;为什么你的下一个工业 HMI 应该用 FPGA ARM&#xff1f; 在工厂车间里&#xff0c;一块响应迟钝的触摸屏可能意味着整条产线停摆。传统的 PLC 触摸屏架构虽然稳定&#xff0c;但在面对复杂图形、多…

作者头像 李华
网站建设 2026/2/25 15:13:48

Qtimer::singleshot实现非阻塞GUI:深度剖析

用 QTimer::singleShot 打造流畅 GUI&#xff1a;从原理到实战的深度实践你有没有遇到过这样的场景&#xff1f;用户点击按钮后&#xff0c;界面瞬间“卡住”&#xff0c;鼠标悬停没反应&#xff0c;窗口拖不动&#xff0c;甚至连关闭按钮都点不了——直到几秒后才突然弹出一个…

作者头像 李华
网站建设 2026/2/26 3:32:21

java springboot基于微信小程序的餐厅食堂美食点餐系统美食活动(源码+文档+运行视频+讲解视频)

文章目录 系列文章目录目的前言一、详细视频演示二、项目部分实现截图三、技术栈 后端框架springboot前端框架vue持久层框架MyBaitsPlus微信小程序介绍系统测试 四、代码参考 源码获取 目的 摘要&#xff1a;为提升餐厅食堂点餐效率与顾客用餐体验&#xff0c;本文探讨基于Ja…

作者头像 李华
网站建设 2026/2/24 3:44:34

【VSCode多模型调试终极指南】:掌握跨模型调试核心技术,效率提升90%

第一章&#xff1a;VSCode多模型调试的核心价值与应用场景在现代软件开发中&#xff0c;系统往往依赖多个协同工作的服务或模型&#xff0c;例如机器学习推理服务、微服务架构中的API模块以及前后端分离的应用组件。VSCode通过其强大的扩展机制和调试协议支持&#xff0c;实现了…

作者头像 李华