news 2026/3/5 2:16:03

Java 线程间的通信方式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 线程间的通信方式

一、概述

在Java中,线程之间的通信主要涉及线程之间如何交换信息或协调行动。常见的线程通信方式有以下几种:

  1. 共享内存(通过共享对象进行通信)
  2. wait/notify机制
  3. Lock和Condition
  4. 使用阻塞队列(BlockingQueue)
  5. 使用管道(PipedInputStream/PipedOutputStream 或 PipedReader/PipedWriter)
  6. 使用信号量(Semaphore)等同步工具
  7. 使用CountDownLatch、CyclicBarrier等同步辅助类
  8. 使用Exchanger
  9. 使用Future和Callable
  10. 使用CompletableFuture

二、详细实现与示例

2.1 共享内存(共享变量)

线程之间通过读写共享的变量来进行通信。这是最常用的一种方式,但需要同步机制来保证数据的一致性(如synchronized、volatile、Lock等)。

// 示例:使用volatile共享变量publicclassSharedVariable{privatevolatilebooleanflag=false;publicvoidsetFlag(){flag=true;}publicvoidwaitForFlag(){while(!flag){// 等待}System.out.println("Flag is true!");}}

2.2 wait()/notify()/notifyAll()机制

这是Object类提供的方法,用于线程间的等待和唤醒。必须搭配synchronized使用,因为wait/notify需要先获得对象的锁。

publicclassWaitNotifyExample{privatefinalObjectlock=newObject();privatebooleancondition=false;// 等待方publicvoidawait()throwsInterruptedException{synchronized(lock){while(!condition){lock.wait();// 释放锁并等待}// 执行后续操作System.out.println("条件满足,继续执行");}}// 通知方publicvoidsignal(){synchronized(lock){condition=true;lock.notify();// 唤醒一个等待线程// lock.notifyAll(); // 唤醒所有等待线程}}}

2.3 Lock和Condition(显式锁)

Lock提供了比synchronized更灵活的锁机制,而Condition则提供了线程间协调等待和唤醒的功能,类似于wait/notify,但可以更精细地控制。

importjava.util.concurrent.locks.*;publicclassLockConditionExample{privatefinalLocklock=newReentrantLock();privatefinalConditioncondition=lock.newCondition();privatebooleanready=false;publicvoidawait()throwsInterruptedException{lock.lock();try{while(!ready){condition.await();// 等待}System.out.println("准备就绪,开始工作");}finally{lock.unlock();}}publicvoidsignal(){lock.lock();try{ready=true;condition.signal();// 发送信号}finally{lock.unlock();}}}

2.4 阻塞队列(BlockingQueue)

BlockingQueue是一个接口,它定义了线程安全的队列,支持阻塞的插入和移除操作。当队列满时,插入操作会被阻塞;当队列空时,移除操作会被阻塞。

importjava.util.concurrent.*;publicclassBlockingQueueExample{privateBlockingQueue<String>queue=newLinkedBlockingQueue<>(10);// 生产者classProducerimplementsRunnable{@Overridepublicvoidrun(){try{Stringitem="item-"+System.currentTimeMillis();queue.put(item);// 队列满时会阻塞System.out.println("生产: "+item);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}}}// 消费者classConsumerimplementsRunnable{@Overridepublicvoidrun(){try{Stringitem=queue.take();// 队列空时会阻塞System.out.println("消费: "+item);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}}}}

2.5 信号量(Semaphore)

信号量用来控制同时访问某个资源的线程数量,也可以用于线程间通信,但更偏向于同步。通过acquire()和release()操作。

importjava.util.concurrent.Semaphore;publicclassSemaphoreExample{privateSemaphoresemaphore=newSemaphore(0);// 初始许可为0publicvoidwaitSignal()throwsInterruptedException{System.out.println("等待信号...");semaphore.acquire();// 获取许可,没有许可时阻塞System.out.println("收到信号,继续执行");}publicvoidsendSignal(){System.out.println("发送信号");semaphore.release();// 释放许可}}

2.6 CountDownLatch

CountDownLatch允许一个或多个线程等待其他线程完成操作;

importjava.util.concurrent.CountDownLatch;publicclassCountDownLatchExample{publicstaticvoidmain(String[]args)throwsInterruptedException{CountDownLatchlatch=newCountDownLatch(3);for(inti=0;i<3;i++){newThread(()->{System.out.println(Thread.currentThread().getName()+" 完成任务");latch.countDown();// 计数器减1}).start();}latch.await();// 等待计数器归零System.out.println("所有任务完成,继续主线程");}}

2.7 CyclicBarrier

CyclicBarrier让一组线程相互等待,到达一个公共屏障点。

importjava.util.concurrent.CyclicBarrier;publicclassCyclicBarrierExample{publicstaticvoidmain(String[]args){CyclicBarrierbarrier=newCyclicBarrier(3,()->{System.out.println("所有线程到达屏障,执行屏障动作");});for(inti=0;i<3;i++){newThread(()->{try{System.out.println(Thread.currentThread().getName()+" 到达屏障");barrier.await();// 等待其他线程System.out.println(Thread.currentThread().getName()+" 继续执行");}catch(Exceptione){e.printStackTrace();}}).start();}}}

2.8 Exchanger

Exchanger用于两个线程之间交换数据。每个线程在exchange()方法处等待,直到两个线程都调用exchange()方法,然后交换数据。

importjava.util.concurrent.Exchanger;publicclassExchangerExample{publicstaticvoidmain(String[]args){Exchanger<String>exchanger=newExchanger<>();newThread(()->{try{Stringdata="Thread1的数据";System.out.println("Thread1发送: "+data);Stringreceived=exchanger.exchange(data);System.out.println("Thread1收到: "+received);}catch(InterruptedExceptione){e.printStackTrace();}}).start();newThread(()->{try{Stringdata="Thread2的数据";System.out.println("Thread2发送: "+data);Stringreceived=exchanger.exchange(data);System.out.println("Thread2收到: "+received);}catch(InterruptedExceptione){e.printStackTrace();}}).start();}}

2.9 管道(Piped Streams)

管道是一种基于流的通信方式,一个线程向管道输出流写数据,另一个线程从管道输入流读数据。这种方式适用于线程间传输数据,但不如阻塞队列常用。

importjava.io.*;publicclassPipedStreamExample{publicstaticvoidmain(String[]args)throwsIOException{PipedOutputStreampos=newPipedOutputStream();PipedInputStreampis=newPipedInputStream(pos);// 写入线程newThread(()->{try{pos.write("Hello from pipe!".getBytes());pos.close();}catch(IOExceptione){e.printStackTrace();}}).start();// 读取线程newThread(()->{try{intdata;while((data=pis.read())!=-1){System.out.print((char)data);}pis.close();}catch(IOExceptione){e.printStackTrace();}}).start();}}

2.10 Future/Callable

通过ExecutorService提交一个Callable任务,返回一个Future对象。主线程可以通过Future.get()方法获取子线程的执行结果,这实际上也是一种线程间通信(获取结果)。

importjava.util.concurrent.*;publicclassFutureExample{publicstaticvoidmain(String[]args)throwsException{ExecutorServiceexecutor=Executors.newSingleThreadExecutor();Callable<String>task=()->{Thread.sleep(1000);return"任务结果";};Future<String>future=executor.submit(task);System.out.println("等待结果...");Stringresult=future.get();// 阻塞等待结果System.out.println("结果: "+result);executor.shutdown();}}

2.11 CompletableFuture(Java 8+)

更强大的异步编程和线程通信。

importjava.util.concurrent.CompletableFuture;publicclassCompletableFutureExample{publicstaticvoidmain(String[]args){// 链式调用和组合CompletableFuture<String>future=CompletableFuture.supplyAsync(()->"Hello").thenApply(s->s+" World").thenApply(String::toUpperCase);future.thenAccept(System.out::println);// 结果: HELLO WORLD}}

三、选择建议

  1. 简单同步:使用synchronized + wait/notify
  2. 复杂同步:使用Lock + Condition
  3. 生产者-消费者:优先选择BlockingQueue
  4. 线程计数/等待:使用CountDownLatch
  5. 线程集合点:使用CyclicBarrier
  6. 数据交换:使用Exchanger
  7. 资源控制:使用Semaphore
  8. 异步结果:使用Future/CompletableFuture

.

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

JasperSoft Studio在零售业数据分析中的5个实战案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个零售业数据分析模板库&#xff0c;包含&#xff1a;1) 库存周转率分析报表&#xff1b;2) 门店销售热力图&#xff1b;3) 会员消费行为分析&#xff1b;4) 促销活动效果评…

作者头像 李华
网站建设 2026/3/4 9:19:24

火山引擎AI大模型对比:GLM-4.6V-Flash-WEB有何优势?

火山引擎AI大模型对比&#xff1a;GLM-4.6V-Flash-WEB有何优势&#xff1f; 在如今的智能应用开发中&#xff0c;一个现实问题正变得越来越突出&#xff1a;我们手握强大的多模态大模型&#xff0c;却常常“用不起来”。不是效果不够好&#xff0c;而是跑得太慢、太贵、太重——…

作者头像 李华
网站建设 2026/3/4 11:48:02

零基础学会Python镜像源配置:图文详解

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个交互式Python镜像源配置助手&#xff0c;功能包括&#xff1a;1. 图形化界面&#xff08;Tkinter&#xff09;显示当前源配置 2. 提供主流镜像源一键切换按钮 3. 测试连接…

作者头像 李华
网站建设 2026/3/4 14:07:13

闪电开发:用NEXT AI DRAWIO快速验证产品原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个基于NEXT AI DRAWIO的快速原型工具&#xff0c;能够根据产品描述自动生成UI流程图和交互原型。要求支持&#xff1a;1&#xff09;从文字需求生成初始原型 2&#xff09;拖…

作者头像 李华
网站建设 2026/3/4 12:27:58

在线电路仿真辅助高校电路原理教学的探索

用一块“虚拟面包板”点亮电路课堂&#xff1a;在线仿真如何重塑高校电路教学在讲授《电路原理》的第十年&#xff0c;我仍会遇到同样的问题——当我在黑板上画出一个RLC串联电路&#xff0c;写下微分方程&#xff0c;再推导出其欠阻尼响应时&#xff0c;台下总有学生皱眉&…

作者头像 李华
网站建设 2026/3/4 13:52:38

如何用GLM-4.6V-Flash-WEB实现低延迟图像问答系统?

如何用GLM-4.6V-Flash-WEB实现低延迟图像问答系统&#xff1f; 在智能客服、在线教育和办公自动化的今天&#xff0c;用户不再满足于“上传图片 → 等待几秒 → 得到结果”的慢节奏交互。他们希望像聊天一样自然地问&#xff1a;“这张发票的金额是多少&#xff1f;”“图表里的…

作者头像 李华