本文目录导读:

我来为你提供一个完整的 wait/notify 生产者-消费者案例,并详细解释其工作原理。
经典生产者-消费者案例
import java.util.LinkedList;
import java.util.Queue;
/**
* 使用 wait/notify 实现生产者-消费者模式
*/
public class ProducerConsumerExample {
// 共享缓冲区
private final Queue<Integer> buffer = new LinkedList<>();
private final int MAX_SIZE = 5; // 缓冲区最大容量
/**
* 生产者:往缓冲区添加数据
*/
public synchronized void produce() throws InterruptedException {
// 当缓冲区已满时,生产者等待
while (buffer.size() == MAX_SIZE) {
System.out.println("【生产者】缓冲区已满,等待消费者消费...");
wait(); // 释放锁并等待
}
// 生产数据
int data = (int) (Math.random() * 100);
buffer.offer(data);
System.out.println("【生产者】生产数据: " + data + ",当前缓冲区大小: " + buffer.size());
// 通知消费者可以消费了
notifyAll();
// 模拟生产过程耗时
Thread.sleep(500);
}
/**
* 消费者:从缓冲区取出数据
*/
public synchronized void consume() throws InterruptedException {
// 当缓冲区为空时,消费者等待
while (buffer.isEmpty()) {
System.out.println("【消费者】缓冲区为空,等待生产者生产...");
wait(); // 释放锁并等待
}
// 消费数据
int data = buffer.poll();
System.out.println("【消费者】消费数据: " + data + ",当前缓冲区大小: " + buffer.size());
// 通知生产者可以继续生产了
notifyAll();
// 模拟消费过程耗时
Thread.sleep(500);
}
/**
* 测试主方法
*/
public static void main(String[] args) {
ProducerConsumerExample example = new ProducerConsumerExample();
// 创建生产者线程
Thread producerThread = new Thread(() -> {
try {
while (true) {
example.produce();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}, "生产者线程");
// 创建消费者线程
Thread consumerThread = new Thread(() -> {
try {
while (true) {
example.consume();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}, "消费者线程");
// 启动线程
producerThread.start();
consumerThread.start();
}
}
改进版本(支持多个生产者消费者)
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 多生产者-多消费者案例
*/
public class MultiProducerConsumer {
private final Queue<Integer> buffer = new LinkedList<>();
private final int MAX_SIZE = 3;
private final AtomicInteger counter = new AtomicInteger(0);
// 锁对象
private final Object lock = new Object();
/**
* 生产者方法
*/
public void produce(String producerName) throws InterruptedException {
synchronized (lock) {
// 使用 while 循环检查条件(防止虚假唤醒)
while (buffer.size() >= MAX_SIZE) {
System.out.println(producerName + ": 缓冲区已满,等待...");
lock.wait(); // 释放 lock 锁
}
int data = counter.incrementAndGet();
buffer.offer(data);
System.out.println(producerName + ": 生产了 " + data + ",当前大小: " + buffer.size());
// 通知所有等待的线程
lock.notifyAll();
Thread.sleep(300);
}
}
/**
* 消费者方法
*/
public void consume(String consumerName) throws InterruptedException {
synchronized (lock) {
// 使用 while 循环检查条件(防止虚假唤醒)
while (buffer.isEmpty()) {
System.out.println(consumerName + ": 缓冲区为空,等待...");
lock.wait(); // 释放 lock 锁
}
int data = buffer.poll();
System.out.println(consumerName + ": 消费了 " + data + ",当前大小: " + buffer.size());
// 通知所有等待的线程
lock.notifyAll();
Thread.sleep(300);
}
}
public static void main(String[] args) {
MultiProducerConsumer example = new MultiProducerConsumer();
// 创建多个生产者
for (int i = 1; i <= 2; i++) {
final String producerName = "生产者" + i;
new Thread(() -> {
try {
while (true) {
example.produce(producerName);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
// 创建多个消费者
for (int i = 1; i <= 2; i++) {
final String consumerName = "消费者" + i;
new Thread(() -> {
try {
while (true) {
example.consume(consumerName);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
}
}
更实用的阻塞队列实现案例
import java.util.LinkedList;
import java.util.Queue;
/**
* 自定义阻塞队列(类似 BlockingQueue 的简单实现)
*/
public class CustomBlockingQueue<T> {
private final Queue<T> queue;
private final int capacity;
private final Object lock = new Object();
public CustomBlockingQueue(int capacity) {
this.queue = new LinkedList<>();
this.capacity = capacity;
}
/**
* 添加元素(如果队列满了,则阻塞)
*/
public void put(T item) throws InterruptedException {
synchronized (lock) {
while (queue.size() >= capacity) {
System.out.println("队列已满," + Thread.currentThread().getName() + " 等待...");
lock.wait();
}
queue.offer(item);
System.out.println(Thread.currentThread().getName() + " 添加: " + item
+ ",队列大小: " + queue.size());
lock.notifyAll();
}
}
/**
* 取出元素(如果队列空了,则阻塞)
*/
public T take() throws InterruptedException {
synchronized (lock) {
while (queue.isEmpty()) {
System.out.println("队列为空," + Thread.currentThread().getName() + " 等待...");
lock.wait();
}
T item = queue.poll();
System.out.println(Thread.currentThread().getName() + " 取出: " + item
+ ",队列大小: " + queue.size());
lock.notifyAll();
return item;
}
}
/**
* 测试
*/
public static void main(String[] args) {
CustomBlockingQueue<Integer> queue = new CustomBlockingQueue<>(3);
// 生产者
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
queue.put(i);
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "生产者").start();
// 消费者
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
queue.take();
Thread.sleep(200);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "消费者").start();
}
}
关键要点和注意事项
wait/notify 必须配合 synchronized 使用
// 正确写法
synchronized (lock) {
while (condition) {
lock.wait();
}
lock.notifyAll();
}
使用 while 而不是 if 检查条件
// ❌ 错误:使用 if 可能产生虚假唤醒问题
if (condition) {
wait();
}
// ✅ 正确:使用 while 防止虚假唤醒
while (condition) {
wait();
}
wait 释放锁的机制
wait()释放对象锁并让出 CPUnotify()随机唤醒一个等待线程(不释放锁)notifyAll()唤醒所有等待线程(不释放锁)
常用方法说明
| 方法 | 作用 | 锁的处理 |
|---|---|---|
wait() |
让当前线程等待 | 释放锁 |
wait(long timeout) |
等待指定时间 | 释放锁 |
notify() |
唤醒一个等待线程 | 不释放锁 |
notifyAll() |
唤醒所有等待线程 | 不释放锁 |
两个线程死锁的简单示例
public class DeadlockExample {
public static void main(String[] args) {
Object lock1 = new Object();
Object lock2 = new Object();
// 线程1
new Thread(() -> {
synchronized (lock1) {
System.out.println("Thread1: 持有 lock1");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock2) {
System.out.println("Thread1: 持有 lock1 和 lock2");
}
}
}).start();
// 线程2(与线程1顺序相反,容易造成死锁)
new Thread(() -> {
synchronized (lock2) {
System.out.println("Thread2: 持有 lock2");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock1) {
System.out.println("Thread2: 持有 lock1 和 lock2");
}
}
}).start();
}
}
生产环境建议
在实际生产环境中,推荐使用 java.util.concurrent 包提供的工具类:
// 使用阻塞队列
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5);
// 生产者
new Thread(() -> {
try {
queue.put(data); // 自动阻塞
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
// 消费者
new Thread(() -> {
try {
int data = queue.take(); // 自动阻塞
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
这些标准库组件已经处理好了线程安全、性能优化等问题,可以减少手动编写 wait/notify 代码。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播