await 和 wait 是两个在 Java 中用于线程同步的关键字。它们的作用都是让线程等待某个条件满足后再继续执行。虽然它们的功能相似,但是在使用上有一些差异。

首先,我们来看一下 await 关键字。它是 Java 5 中引入的一个新特性,用于配合使用 Lock 和 Condition 来实现线程等待和唤醒的功能。在使用 await 之前,我们需要先获取 Lock 对象,并通过 Lock 对象的 newCondition 方法创建一个 Condition 对象。

await 方法会将当前线程放入到等待队列中,然后释放 Lock 对象的锁,让其他线程有机会获取锁并执行。当某个条件满足时,我们可以调用 Condition 对象的 signal 或 signalAll 方法来唤醒等待队列中的线程。

下面是一个使用 await 和 signal 来实现生产者消费者模型的例子:

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ProducerConsumer {
    private final int capacity;
    private final Queue<Integer> queue;
    private final Lock lock;
    private final Condition notEmpty;
    private final Condition notFull;

    public ProducerConsumer(int capacity) {
        this.capacity = capacity;
        this.queue = new LinkedList<>();
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        this.notFull = lock.newCondition();
    }

    public void produce(int num) throws InterruptedException {
        lock.lock();
        try {
            while (queue.size() == capacity) {
                notFull.await();
            }
            queue.add(num);
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public int consume() throws InterruptedException {
        lock.lock();
        try {
            while (queue.isEmpty()) {
                notEmpty.await();
            }
            int num = queue.poll();
            notFull.signal();
            return num;
        } finally {
            lock.unlock();
        }
    }
}

上面的代码中,我们使用了一个容量为 capacity 的队列来保存生产者生产的数据,当队列满时生产者需要等待,当队列为空时消费者需要等待。通过使用 await 和 signal 方法,我们可以实现生产者和消费者之间的同步。

接下来,我们来看一下 wait 关键字。它是 Java 中 Object 类的一个方法,用于让当前线程进入等待状态,并释放对象的锁。通过调用对象的 notify 或 notifyAll 方法,我们可以唤醒等待中的线程。

下面是一个使用 wait 和 notify 来实现生产者消费者模型的例子:

import java.util.LinkedList;
import java.util.Queue;

public class ProducerConsumer {
    private final int capacity;
    private final Queue<Integer> queue;

    public ProducerConsumer(int capacity) {
        this.capacity = capacity;
        this.queue = new LinkedList<>();
    }

    public synchronized void produce(int num) throws InterruptedException {
        while (queue.size() == capacity) {
            wait();
        }
        queue.add(num);
        notifyAll();
    }

    public synchronized int consume() throws InterruptedException {
        while (queue.isEmpty()) {
            wait();
        }
        int num = queue.poll();
        notifyAll();
        return num;
    }
}

上面的代码中,我们使用了一个容量为 capacity 的队列来保存生产者生产的数据,当队列满时生产者需要等待,当队列为空时消费者需要等待。通过使用 wait 和 notifyAll 方法,我们可以实现生产者和消费者之间的同步。

总结起来,await 和 wait 都是用于线程同步的关键字,它们可以让线程等待某个条件满足后再继续执行。await 是 Java 5 中引入的新特性,需要配合 Lock 和 Condition 使用;而 wait 是 Object 类的方法,可以直接在同步方法或同步代码块中使用。

流程图如下:

flowchart TD
    subgraph await
        A[获取锁] --> B[判断条件]
        B -- 条件满足 --> C[执行]
        B -- 条件不满足 --> D[等待]
        C --> E[释放锁]
        D --> E
    end
    
    subgraph wait
        F[获取锁] --> G[判断条件]
        G -- 条件满足 --> H[执行]
        G -- 条件