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 -- 条件