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

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

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. 使用 LockCondition

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

示例代码
复制代码

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 接口提供了一种线程安全的队列实现,支持在队列满时等待生产和在队列空时等待消费。常见的实现类有 ArrayBlockingQueueLinkedBlockingQueue 等。

示例代码
复制代码

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. LockCondition:提供了更灵活和细粒度的控制,通过显式的锁和条件对象进行线程同步。
  3. BlockingQueue:内置的线程安全队列,实现了生产者-消费者模式,简化了线程间的通信和同步。

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

相关推荐
月亮不月亮4 分钟前
月亮商场购物打折Java
java·eclipse
guozhetao13 分钟前
【ST表、倍增】P7167 [eJOI 2020] Fountain (Day1)
java·c++·python·算法·leetcode·深度优先·图论
技术思考者14 分钟前
基础很薄弱如何规划考研
java·经验分享·考研
●VON37 分钟前
重生之我在暑假学习微服务第二天《MybatisPlus-下篇》
java·学习·微服务·架构·mybatis-plus
老华带你飞37 分钟前
口腔助手|口腔挂号预约小程序|基于微信小程序的口腔门诊预约系统的设计与实现(源码+数据库+文档)
java·数据库·微信小程序·小程序·论文·毕设·口腔小程序
枫叶丹439 分钟前
【Qt开发】信号与槽(二)-> 信号和槽的使用
开发语言·qt
hqxstudying1 小时前
J2EE模式---服务层模式
java·数据库·后端·spring·oracle·java-ee
GM_8281 小时前
【最新最完整】SpringAI-1.0.0开发MCP Server,搭建MCP Client 实战笔记(进阶+详细+完整代码)
java·后端·ai编程·springai·mcp
都叫我大帅哥1 小时前
Java DelayQueue:时间管理大师的终极武器
java
秋千码途1 小时前
小架构step系列27:Hibernate提供的validator
java·spring·架构·hibernate