news 2026/2/8 15:26:21

线程间通信的秘密:如何让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/2 5:38:55

java springboot基于微信小程序的社区服务系统社区设施维修缴费(源码+文档+运行视频+讲解视频)

文章目录 系列文章目录目的前言一、详细视频演示二、项目部分实现截图三、技术栈 后端框架springboot前端框架vue持久层框架MyBaitsPlus微信小程序介绍系统测试 四、代码参考 源码获取 目的 摘要&#xff1a;针对传统社区设施维修缴费流程繁琐、信息不透明等问题&#xff0c;…

作者头像 李华
网站建设 2026/2/4 16:46:44

百考通AI一键生成专业任务书,让科研开题快人一步!

对于每一位踏入科研殿堂的学子或初涉项目管理的职场新人而言&#xff0c;“开题报告”或“任务书”的撰写&#xff0c;往往是一道令人望而生畏的坎。它要求作者不仅要清晰阐述研究目标、技术路线和预期成果&#xff0c;更要具备严谨的逻辑思维和规范的学术表达能力。面对浩如烟…

作者头像 李华
网站建设 2026/2/5 9:09:46

如何通过ms-swift实现虚拟现实展览设计?

如何通过 ms-swift 实现虚拟现实展览设计&#xff1f; 在数字策展逐渐成为主流的今天&#xff0c;一场宋代瓷器展不再需要千里调运文物、搭建实体展馆。只需输入“打造沉浸式宋瓷美学空间”&#xff0c;AI 就能自动生成展厅布局、撰写诗意解说词&#xff0c;并匹配符合宋代审美…

作者头像 李华
网站建设 2026/2/5 21:43:10

远程开发变慢?你必须知道的VSCode Agent HQ性能瓶颈突破方法

第一章&#xff1a;远程开发变慢&#xff1f;VSCode Agent HQ性能瓶颈的真相在使用 VSCode 远程开发&#xff08;Remote-SSH、WSL 或 Containers&#xff09;时&#xff0c;开发者常遇到响应延迟、文件同步卡顿、语言服务加载缓慢等问题。这些问题往往被归咎于网络环境&#xf…

作者头像 李华
网站建设 2026/2/7 5:22:15

结合Qwen3Guard-Gen-8B打造符合中国法规的AI内容生态

结合Qwen3Guard-Gen-8B打造符合中国法规的AI内容生态 在生成式人工智能迅速渗透到社交、客服、政务等关键场景的今天&#xff0c;一个不容忽视的问题浮出水面&#xff1a;如何让大模型“说合适的话”&#xff1f;尤其是在中国这样网络内容监管严格、舆情敏感度高的环境中&#…

作者头像 李华
网站建设 2026/1/30 16:15:04

企业DevOps必看,VSCode集成Entra ID的7大核心优势与实施要点

第一章&#xff1a;VSCode Entra ID 登录Visual Studio Code&#xff08;VSCode&#xff09;作为广受欢迎的轻量级代码编辑器&#xff0c;支持通过 Microsoft Entra ID&#xff08;前身为 Azure Active Directory&#xff09;实现安全的身份验证与资源访问。通过集成 Entra ID&…

作者头像 李华