线程间的通讯
·
线程通信是指同一个进程内的多个线程,相互传递数据、协调执行顺序的机制。
因为多线程共享进程的内存空间,通信比进程间通信简单,但也需要解决线程安全、同步、数据传递三大问题。
一、核心本质

多个线程协作,共享数据、交替执行、传递消息。
-
为什么需要线程通信?
- 线程 A 计算完结果,需要交给线程 B 使用
- 控制执行顺序:线程 B 必须等线程 A 执行完再运行
- 多个线程操作共享数据,防止冲突(线程安全)
-
线程通信的本质
- 共享变量 + 同步机制
- 等待 / 唤醒机制
- 管道 / 队列传输
二、5 种常用通信方式
1. 共享变量(volatile)
- 作用:用于状态标记,保证变量可见性。
- 原理:可见性,线程读到最新主内存数据
- 用法:
volatile boolean flag启停线程 - 缺点:无法精准控制执行顺序
2. wait /notify/notifyAll(Object 方法)
- 必须在synchronized 锁内使用,用于等待 - 唤醒。
- wait:释放锁,进入等待
- notify:随机唤醒一个等待线程
- notifyAll:唤醒所有等待线程
- 场景:生产者消费者
3. Lock + Condition(JDK1.5 以后)
- 替代 wait/notify,比
synchronized更灵活,精准唤醒指定线程 - 可创建多个条件队列,分工等待唤醒
Lock lock = new ReentrantLock();
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
4. 阻塞队列 BlockingQueue(最常用)
自动实现等待、唤醒、线程安全,不用写 wait/notify。
BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
// 生产者
queue.put("数据");
// 消费者
String data = queue.take();
put():满了就阻塞take():空了就阻塞
✅ 开发首选,简单、安全、不易出错。
5. 管道流 PipedInputStream / PipedOutputStream
- 线程间直接字节数据传递
- 多用于字节消息传输
6. 工具类通信
- CountDownLatch(闭锁):等待所有线程做完再执行
- CyclicBarrier(栅栏):线程集齐再一起出发
- Semaphore(信号量):控制并发线程数
三、Java 多线程并发工具类
闭锁(CountDownLatch)与 栅栏(CyclicBarrier)是Java 多线程并发工具类,专门用来控制线程执行顺序、协调多线程同步。
1. CountDownLatch(门栓、倒计时锁)
核心一句话:等所有线程都干完,主线程再继续执行。像倒计时,倒计时结束,门才打开。
核心特点:
- 一次性使用:计数到 0 就结束,不能重置
- 等待方是主线程:主线程等其他线程
- 作用:等待一批线程执行完成
常用方法:
new CountDownLatch(int count):初始化计数器countDown():计数器 -1await():阻塞等待,直到计数器 = 0
经典场景:
- 主线程等 5 个初始化线程全部完成,再开始运行
- 游戏加载:等所有资源加载完,才进入游戏
// 主线程等 3 个线程执行完
CountDownLatch latch = new CountDownLatch(3);
// 线程执行完,计数器-1
new Thread(() -> {
latch.countDown();
}).start();
// 主线程阻塞等待
latch.await();
2. CyclicBarrier(循环屏障)
核心一句话:一组线程互相等待,全部到齐后,再一起同时执行。像聚会,所有人到齐了,才开饭
核心特点:
- 可循环使用:执行完一轮,可以继续用
- 线程之间互相等待
- 作用:一组线程同步开始执行
常用方法:
new CyclicBarrier(int parties):等待的线程数await():我到了,等其他人
经典场景:
- 多线程同时开始执行压测
- 所有线程准备好,同时开始执行任务
// 3 个线程互相等待
CyclicBarrier barrier = new CyclicBarrier(3);
new Thread(() -> {
// 等待其他线程
barrier.await();
// 所有线程到齐后,同时执行这里
}).start();
3. Semaphore(信号量)
Semaphore = 许可证管理器 → 控制同时能运行的线程数量!
核心原理:
- ① 初始化设置许可证数量
- ② 线程要执行,必须先获取许可证
- ③ 用完必须归还许可证
- ④ 没许可证 → 线程阻塞等待
常用方法:
// 1. 创建:指定许可证数量
Semaphore semaphore = new Semaphore(3);
// 2. 获取许可证(获取不到就阻塞)
semaphore.acquire();
// 3. 归还许可证
semaphore.release();
常用场景:
- 接口限流(最多 N 个请求同时访问)
- 池化资源控制(数据库连接池、线程池)
- 共享资源限流(文件读写、打印机)
四、一句话区分
- 共享变量:看信号
- wait/notify:阻塞唤醒
- 实际开发优先用阻塞队列,最简单安全
- 阻塞队列:安全传数据
- 闭锁 栅栏:批量等待协作
- 工作中:等待完成用闭锁,同步开始用栅栏
- CountDownLatch:倒计时,主线程等待,不可重用
- CyclicBarrier:循环屏障,线程互相等待,可重用
- Semaphore 用来限流
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)