停等机制
等待/通知机制,是指一个线程A调用了对象O的wait()方法进入等待状态,而另一个线程B调用了对象O的notify()或者notifyAll()方法,线程A收到通知后从对象O的wait()方法返回,进而执行后续操作。上述两个线程通过对象O来完成交互,而对象上的wait()和notify/notifyAll()的关系就如同开关信号一样,用来完成等待方和通知方之间的交互工作。
阻塞队列
有多个生产者和消费者线程,还有一个固定大小的共享队列,用于存生产的元素,生产者负责生产元素,如果队列满了,阻塞等待,当又有空位置时,再唤醒阻塞的生产者线程,消费者同理。
实现:
import java.util.LinkedList;
import java.util.Queue;
public class BlockingQueue<T> {
private final Queue<T> queue = new LinkedList<>();
private final int maxSize;
private final Object lock = new Object();
public BlockingQueue(int maxSize) {
this.maxSize = maxSize;
}
public void put(T element) throws InterruptedException {
synchronized (lock) {
while (queue.size() == maxSize) {
System.out.println("队列满了"+Thread.currentThread().getName() +"线程等待");
lock.wait(); // 队列满时,生产者线程等待
}
queue.add(element);
System.out.println(Thread.currentThread().getName() + " 生产者生产: " + element);
lock.notifyAll(); // 添加元素后,通知等待的消费者线程
}
}
public T take() throws InterruptedException {
synchronized (lock) {
while (queue.isEmpty()) {
lock.wait(); // 队列空时,消费者线程等待
System.out.println("队列空了"+Thread.currentThread().getName() +"线程等待");
}
T element = queue.poll();
System.out.println(Thread.currentThread().getName() + " 消费者消费: " + element);
lock.notifyAll(); // 取出元素后,通知等待的生产者线程
return element;
}
}
public static void main(String[] args) {
BlockingQueue<Integer> blockingQueue = new BlockingQueue<>(5);
// 生产者线程
Runnable producer = () -> {
for (int i = 0; i < 10; i++) {
try {
blockingQueue.put(i);
Thread.sleep(1000); // 模拟生产时间
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
};
// 消费者线程
Runnable consumer = () -> {
for (int i = 0; i < 10; i++) {
try {
blockingQueue.take();
Thread.sleep(1000); // 模拟消费时间
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
};
// 创建并启动多个生产者线程
Thread producerThread1 = new Thread(producer, "生产者1");
Thread producerThread2 = new Thread(producer, "生产者2");
producerThread1.start();
producerThread2.start();
// 创建并启动多个消费者线程
Thread consumerThread1 = new Thread(consumer, "消费者1");
Thread consumerThread2 = new Thread(consumer, "消费者2");
consumerThread1.start();
consumerThread2.start();
}
}
BlockingQueue 类:
- 定义了一个阻塞队列,使用
LinkedList
作为内部存储,并定义了最大容量maxSize
。 put
方法用于生产产品。当队列已满时,生产者线程调用lock.wait()
方法进入等待状态,直到有空间可以添加新产品。每当添加新产品后,通过调用lock.notifyAll()
方法通知所有等待的消费者线程。take
方法用于消费产品。当队列为空时,消费者线程调用lock.wait()
方法进入等待状态,直到有产品可以消费。每当取出产品后,通过调用lock.notifyAll()
方法通知所有等待的生产者线程。
生产者和消费者线程:
producer
是一个生产者线程的任务,每隔1000毫秒生产一个产品,生产10个产品。consumer
是一个消费者线程的任务,每隔1000毫秒消费一个产品,消费10个产品。
主方法:
创建并启动多个生产者线程和消费者线程。