当前位置: 首页 > news >正文

Java 中线程之间如何进行通信?

在 Java 中,线程间通信主要通过共享内存线程同步机制实现。以下是核心方法及代码示例:


一、基础通信机制

1.使用wait()/notify()/notifyAll()

这是最经典的线程通信方式,需在synchronized块中使用:

// 共享资源类classMessage{privateStringcontent;privatebooleanempty=true;publicsynchronizedStringread(){while(empty){// 循环检查条件,防止虚假唤醒try{wait();// 释放锁,等待写入}catch(InterruptedExceptione){Thread.currentThread().interrupt();}}empty=true;notifyAll();// 通知所有等待线程returncontent;}publicsynchronizedvoidwrite(Stringmessage){while(!empty){// 等待读取完成try{wait();}catch(InterruptedExceptione){Thread.currentThread().interrupt();}}empty=false;this.content=message;notifyAll();// 通知等待的读取线程}}// 测试代码publicclassWaitNotifyDemo{publicstaticvoidmain(String[]args){Messagemessage=newMessage();// 写入线程Threadwriter=newThread(()->{String[]messages={"消息1","消息2","消息3"};for(Stringmsg:messages){message.write(msg);System.out.println("写入: "+msg);}});// 读取线程Threadreader=newThread(()->{for(inti=0;i<3;i++){Stringmsg=message.read();System.out.println("读取: "+msg);}});reader.start();writer.start();}}

2.使用BlockingQueue(推荐)

Java 并发包提供了现成的线程安全队列:

importjava.util.concurrent.BlockingQueue;importjava.util.concurrent.LinkedBlockingQueue;publicclassBlockingQueueDemo{publicstaticvoidmain(String[]args){// 创建容量为10的阻塞队列BlockingQueue<String>queue=newLinkedBlockingQueue<>(10);// 生产者线程Threadproducer=newThread(()->{try{for(inti=1;i<=5;i++){Stringmessage="消息-"+i;queue.put(message);// 队列满时自动阻塞System.out.println("生产: "+message);Thread.sleep(1000);}queue.put("END");// 结束标志}catch(InterruptedExceptione){Thread.currentThread().interrupt();}});// 消费者线程Threadconsumer=newThread(()->{try{Stringmessage;while(!(message=queue.take()).equals("END")){// 队列空时自动阻塞System.out.println("消费: "+message);}System.out.println("消费者结束");}catch(InterruptedExceptione){Thread.currentThread().interrupt();}});producer.start();consumer.start();}}

二、高级通信工具

3.使用CountDownLatch

适用于一个线程等待多个线程完成:

importjava.util.concurrent.CountDownLatch;publicclassCountDownLatchDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{intworkerCount=3;CountDownLatchstartSignal=newCountDownLatch(1);// 开始信号CountDownLatchdoneSignal=newCountDownLatch(workerCount);// 完成信号for(inti=0;i<workerCount;i++){newThread(newWorker(startSignal,doneSignal),"工人-"+i).start();}System.out.println("主线程: 准备工作完成,通知工人开始工作");startSignal.countDown();// 发出开始信号doneSignal.await();// 等待所有工人完成System.out.println("主线程: 所有工人工作完成");}staticclassWorkerimplementsRunnable{privatefinalCountDownLatchstartSignal;privatefinalCountDownLatchdoneSignal;Worker(CountDownLatchstartSignal,CountDownLatchdoneSignal){this.startSignal=startSignal;this.doneSignal=doneSignal;}@Overridepublicvoidrun(){try{startSignal.await();// 等待开始信号System.out.println(Thread.currentThread().getName()+" 正在工作...");Thread.sleep(2000);// 模拟工作时间System.out.println(Thread.currentThread().getName()+" 工作完成");doneSignal.countDown();// 通知完成}catch(InterruptedExceptione){Thread.currentThread().interrupt();}}}}

4.使用CyclicBarrier

适用于多个线程相互等待:

importjava.util.concurrent.BrokenBarrierException;importjava.util.concurrent.CyclicBarrier;publicclassCyclicBarrierDemo{publicstaticvoidmain(String[]args){intthreadCount=3;CyclicBarrierbarrier=newCyclicBarrier(threadCount,()->{System.out.println("所有线程已就位,开始下一阶段");});for(inti=0;i<threadCount;i++){newThread(newTask(barrier),"线程-"+i).start();}}staticclassTaskimplementsRunnable{privatefinalCyclicBarrierbarrier;Task(CyclicBarrierbarrier){this.barrier=barrier;}@Overridepublicvoidrun(){try{System.out.println(Thread.currentThread().getName()+" 完成阶段1");barrier.await();// 等待其他线程System.out.println(Thread.currentThread().getName()+" 完成阶段2");barrier.await();System.out.println(Thread.currentThread().getName()+" 全部完成");}catch(InterruptedException|BrokenBarrierExceptione){Thread.currentThread().interrupt();}}}}

三、选择建议

场景推荐方案优点
简单的生产消费模式BlockingQueue无需手动同步,代码简洁
复杂条件等待wait()/notify()灵活性高,可精确控制
主线程等待子线程CountDownLatch一次性使用,简单直观
多线程协同工作CyclicBarrier可重复使用,适合分阶段任务

注意事项

  1. 避免死锁:确保锁的获取顺序一致
  2. 防止虚假唤醒:始终在循环中检查条件
  3. 优先使用高层工具:如BlockingQueue比手动wait/notify更安全

根据具体需求选择合适的通信机制,可以显著提高多线程程序的可靠性和性能。

http://www.jsqmd.com/news/454334/

相关文章:

  • 无界等待:系统故障的隐形杀手
  • 四参数随机生长法(QSGS算法)在随机孔隙结构与微观孔隙优化处理中的应用:多孔介质随机生长软件...
  • 小程序商城制作流程,专业商城系统开发 - 码云数智
  • 连接、控制与精进:深入探索 Psycopg2 的现代 PostgreSQL 开发实践
  • 英伟达受挫,TPU能否改写算力格局?
  • 美校申请不内耗!十大留学中介实力护航冲藤校 - 博客湾
  • 【声呐技术】窄带干扰抑制技术:一项综述
  • 穿越周期:国际物流新格局下的理性选择与价值发现 - 品牌评测官
  • AI驱动的数据分类分级实战:从入门到进阶的自动化识别指南
  • 2005-2024年全国城市域名备案数据库
  • 零基础实战:靶场商场网站漏洞利用与安全测试
  • 留学中介TOP10实测|文书全流程服务最能打? - 博客湾
  • 【阅读笔记】OpenClaw入门
  • 【飞机】基于matlab光流的着陆和悬停机动仿真【含Matlab源码 15124期】
  • 2026国际物流公司怎么选?干货解析+权威数据,避开陷阱不踩坑 - 品牌评测官
  • 全开源代码:BLDC PMSM FOC控制程序,有感无感驱动及滑膜霍尔编码器实现
  • COMSOL光学模型下的手性小球特性分析与模拟研究
  • 1975-2030年全球1km分辨率人口空间分布栅格数据
  • 北京留学机构TOP10优选!解锁名校申请捷径 - 博客湾
  • 【声呐技术】FS2-DETR:基于Transformer的增强特征感知小样本声呐目标检测
  • 2026年首个基于OpenClaw pi内核的商用桌面AI私域助理
  • 北京留学机构:靠谱平台助力打造高质量申请 - 博客湾
  • 互联网最常用的加密通信技术
  • 【信道估计】大规模MIMO-OFDM系统的5G通信信道估计算法研究【含Matlab源码 15125期】含文献
  • 从零实现一个进程池(基于管道通信)
  • 【快速EI检索 | SPIE出版】2026 年智能信号与图像处理国际学术会议(ISIP 2026)
  • 全球电动滚筒市场发展趋势分析
  • FOMO All In One
  • 第三部分 — 服务工作者(后台)chrome.runtime 是什么(在 MV3 的说法中)
  • matlab画图工具