Java中的wait和notify、Condition接口的使用

发布于:2025-07-13 ⋅ 阅读:(17) ⋅ 点赞:(0)

Java中的wait和notify机制

基础概念

在Java中,wait()notify()Object类的原生方法,用于实现线程间的协作:

  1. wait()

    • 使当前线程释放对象锁并进入等待状态
    • 必须在synchronized代码块内调用
    • 语法:obj.wait()obj.wait(long timeout)
    • 线程状态变化:RUNNING → WAITING
  2. notify()

    • 随机唤醒一个在该对象上等待的线程
    • notifyAll()唤醒所有等待线程
    • 同样必须在synchronized代码块内调用
// 生产者-消费者示例
class Buffer {
    private int data;
    private boolean available = false;

    public synchronized void produce(int value) {
        while (available) wait();  // 等待消费者取走数据
        data = value;
        available = true;
        notifyAll();  // 唤醒消费者
    }

    public synchronized int consume() {
        while (!available) wait();  // 等待生产者写入数据
        available = false;
        notifyAll();  // 唤醒生产者
        return data;
    }
}

执行流程
graph LR
    A[线程调用wait] --> B[释放对象锁]
    B --> C[进入等待队列]
    D[其他线程调用notify] --> E[唤醒等待线程]
    E --> F[线程尝试重新获取锁]
    F --> G[获取锁后继续执行]


Condition接口(java.util.concurrent.locks)

核心方法

Condition接口提供了更灵活的线程协调机制,需配合Lock使用:

  1. await()

    • 功能类似wait(),但支持更丰富的等待条件
    • 可响应中断:awaitUninterruptibly()
    • 支持超时:await(long time, TimeUnit unit)
  2. signal()

    • 唤醒单个等待线程(类似notify()
    • signalAll()唤醒所有等待线程
使用示例
import java.util.concurrent.locks.*;

class ConditionExample {
    private final Lock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();
    private int[] buffer = new int[10];
    private int count = 0;

    public void produce(int item) throws InterruptedException {
        lock.lock();
        try {
            while (count == buffer.length) 
                notFull.await();  // 缓冲区满时等待
            buffer[count++] = item;
            notEmpty.signal();   // 唤醒消费者
        } finally {
            lock.unlock();
        }
    }

    public int consume() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0) 
                notEmpty.await();  // 缓冲区空时等待
            int item = buffer[--count];
            notFull.signal();      // 唤醒生产者
            return item;
        } finally {
            lock.unlock();
        }
    }
}


对比分析

特性 wait/notify Condition
锁机制 必须配合synchronized 必须配合Lock实现
多条件等待 不支持 支持创建多个Condition实例
中断响应 仅基础中断 提供awaitUninterruptibly()
超时控制 有限支持 精确到纳秒的超时控制
公平性 依赖synchronized 可通过ReentrantLock配置
唤醒精确性 notify随机唤醒 signal可定向唤醒特定条件队列

最佳实践

  1. 循环检查条件
    始终在循环中检查等待条件,避免虚假唤醒:

    while (!condition) {
        obj.wait();
    }
    

  2. 资源释放
    使用try-finally确保锁释放:

    lock.lock();
    try {
        // 临界区代码
    } finally {
        lock.unlock();
    }
    

  3. 选择建议

    • 简单场景:优先使用synchronized + wait/notify
    • 复杂同步:使用Lock + Condition(如多条件队列、公平锁需求)

注意:Java 5+推荐使用java.util.concurrent包中的高级同步工具(如BlockingQueue),仅在底层控制需要时使用wait/notify或Condition。


网站公告

今日签到

点亮在社区的每一天
去签到