两个线程之间是如何通信的呢?

在 Java 中,线程之间的通信(Inter-thread Communication)是指多个线程在程序中共享数据时进行的协作和同步。线程间通信的主要目的是协调线程的工作,确保数据的一致性和正确性,避免竞争条件和死锁。常见的线程通信机制包括 wait() 方法、notify() 方法和 notifyAll() 方法,以及更高级的并发工具类,如 Lock、Condition、BlockingQueue 等。下面详细介绍这些机制和工具。

1. 使用 wait()、notify() 和 notifyAll()

这些方法是 Object 类的一部分,用于在同步代码块或方法中实现线程间的等待/通知机制。它们必须在同步代码块或方法中调用。

wait()
  • 使当前线程进入等待状态,直到其他线程调用 notify() 或 notifyAll() 方法唤醒它。
  • 当前线程必须持有对象的监视器锁。
notify()
  • 唤醒一个等待线程。如果有多个线程在等待,则随机选择一个唤醒。
  • 唤醒的线程必须重新获取监视器锁才能继续执行。
notifyAll()
  • 唤醒所有等待线程。唤醒的线程会竞争监视器锁,只有一个线程能获得锁并继续执行。
示例代码
复制代码

java复制代码

class SharedResource { private int value = 0; private boolean available = false; public synchronized void produce(int newValue) throws InterruptedException { while (available) { wait(); } value = newValue; available = true; notify(); } public synchronized int consume() throws InterruptedException { while (!available) { wait(); } available = false; notify(); return value; } } class Producer extends Thread { private SharedResource resource; public Producer(SharedResource resource) { this.resource = resource; } @Override public void run() { try { for (int i = 1; i <= 5; i++) { resource.produce(i); System.out.println("Produced: " + i); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } } class Consumer extends Thread { private SharedResource resource; public Consumer(SharedResource resource) { this.resource = resource; } @Override public void run() { try { for (int i = 1; i <= 5; i++) { int value = resource.consume(); System.out.println("Consumed: " + value); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } } } public class WaitNotifyExample { public static void main(String[] args) { SharedResource resource = new SharedResource(); new Producer(resource).start(); new Consumer(resource).start(); } }

2. 使用 Lock 和 Condition

java.util.concurrent.locks 包中的 Lock 和 Condition 接口提供了更灵活和强大的线程同步机制。与内置的锁和条件相比,Lock 和 Condition 提供了更细粒度的控制。

示例代码
复制代码

java复制代码

import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.Condition; class SharedResource { private int value = 0; private boolean available = false; private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); public void produce(int newValue) throws InterruptedException { lock.lock(); try { while (available) { condition.await(); } value = newValue; available = true; condition.signal(); } finally { lock.unlock(); } } public int consume() throws InterruptedException { lock.lock(); try { while (!available) { condition.await(); } available = false; condition.signal(); return value; } finally { lock.unlock(); } } } class Producer extends Thread { private SharedResource resource; public Producer(SharedResource resource) { this.resource = resource; } @Override public void run() { try { for (int i = 1; i <= 5; i++) { resource.produce(i); System.out.println("Produced: " + i); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } } class Consumer extends Thread { private SharedResource resource; public Consumer(SharedResource resource) { this.resource = resource; } @Override public void run() { try { for (int i = 1; i <= 5; i++) { int value = resource.consume(); System.out.println("Consumed: " + value); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } } } public class LockConditionExample { public static void main(String[] args) { SharedResource resource = new SharedResource(); new Producer(resource).start(); new Consumer(resource).start(); } }

3. 使用 BlockingQueue

java.util.concurrent 包中的 BlockingQueue 接口提供了一种线程安全的队列实现,支持在队列满时等待生产和在队列空时等待消费。常见的实现类有 ArrayBlockingQueue、LinkedBlockingQueue 等。

示例代码
复制代码

java复制代码

import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; class Producer extends Thread { private BlockingQueue<Integer> queue; public Producer(BlockingQueue<Integer> queue) { this.queue = queue; } @Override public void run() { try { for (int i = 1; i <= 5; i++) { queue.put(i); System.out.println("Produced: " + i); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } } class Consumer extends Thread { private BlockingQueue<Integer> queue; public Consumer(BlockingQueue<Integer> queue) { this.queue = queue; } @Override public void run() { try { for (int i = 1; i <= 5; i++) { int value = queue.take(); System.out.println("Consumed: " + value); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } } } public class BlockingQueueExample { public static void main(String[] args) { BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5); new Producer(queue).start(); new Consumer(queue).start(); } }

总结

在 Java 中,线程之间的通信可以通过多种机制实现:

  1. wait()、notify() 和 notifyAll():基于对象监视器的等待/通知机制,需在同步代码块或方法中使用。
  2. Lock 和 Condition:提供了更灵活和细粒度的控制,通过显式的锁和条件对象进行线程同步。
  3. BlockingQueue:内置的线程安全队列,实现了生产者-消费者模式,简化了线程间的通信和同步。

选择合适的线程通信机制可以提高程序的效率和可靠性,并简化并发编程的复杂性。

相关推荐
淡海水几秒前
05-03-源码-Boehm GC分配与碎片管理
开发语言·算法·unity·c#·游戏引擎·gc
努力实干3 分钟前
C++ 面向对象与工程架构
开发语言·c++·架构
十年Java程序媛9 分钟前
JVM 基础与 GC 垃圾回收详解|可达性分析、分代模型、垃圾收集器、STW
java·开发语言·jvm·spring boot·后端·面试
估值探索者10 分钟前
【Python量化选股流水线 #03】候选股怎么排序?动量+低波+流动性三因子打分取 Top-N
开发语言·python·接口·api接口·股票数据接口·数据接口·股票数据api接口
骑士雄师11 分钟前
supervisor 中关于上下文多轮信息维护常用到的python语法
开发语言·python
曹牧20 分钟前
C#:字符串占位符与值数量不一致
开发语言·数据库·c#
2301_322414280422 分钟前
基于SSM框架的在线考试管理系统的设计与实现14750-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·redis·mysql·tomcat·maven·mybatis·ssm
clz131452128 分钟前
RuoYi-Cloud 新建微服务并实现服务间调用(OpenFeign 实战)
java·ruoyi
迅猛龙办公室28 分钟前
Python函数实现反转一个只有3位数的整数
开发语言·前端·python
“AI国潮设计-小江”31 分钟前
《【AIGC实战】Python+SDXL批量生成“英歌舞树莓香草布丁”IP,附保持角色一致性的代码逻辑》
开发语言·人工智能·python·prompt·aigc