使用 wait()/notify() 實現線程協作,環形陣列作為緩衝區,支援多生產者/消費者、優雅啟停。
synchronized 保護、wait/notify 協作warehouse.storage()warehouse.get() → 消費產品public class Warehouse {
private final Product[] products;
private int front = 0, rear = 0; // [front, rear) 為有效資料
private final int capacity;
public Warehouse(int capacity) {
this.capacity = capacity + 1; // 浪費一格區分滿/空
this.products = new Product[this.capacity];
}
// 消費者取產品
public synchronized Product getProduct() throws InterruptedException {
while (front == rear) { // 空
wait();
}
Product p = products[front];
front = (front + 1) % capacity;
notifyAll(); // 喚醒生產者
return p;
}
// 生產者存產品
public synchronized void storageProduct(Product p) throws InterruptedException {
while ((rear + 1) % capacity == front) { // 滿
wait();
}
products[rear] = p;
rear = (rear + 1) % capacity;
notifyAll(); // 喚醒消費者
}
}
public class Producer extends Thread {
private final Warehouse warehouse;
private volatile boolean running = true;
private static int seq = 0;
public Producer(Warehouse w, String name) { super(name); this.warehouse = w; }
@Override public void run() {
while (running) {
try {
warehouse.storageProduct(new Product("P-" + (++seq)));
Thread.sleep(300);
} catch (InterruptedException e) { break; }
}
}
public void shutdown() { running = false; interrupt(); }
}
public class Consumer extends Thread {
private final Warehouse warehouse;
private volatile boolean running = true;
public Consumer(Warehouse w, String name) { super(name); this.warehouse = w; }
@Override public void run() {
while (running) {
try {
Product p = warehouse.getProduct();
System.out.println(getName() + " 消費: " + p);
Thread.sleep(500);
} catch (InterruptedException e) { break; }
}
}
public void shutdown() { running = false; interrupt(); }
}
public class TestProduct {
public static void main(String[] args) throws InterruptedException {
Warehouse warehouse = new Warehouse(10);
Thread[] producers = {new Producer(warehouse, "P1"), new Producer(warehouse, "P2")};
Thread[] consumers = {new Consumer(warehouse, "C1"), new Consumer(warehouse, "C2"), new Consumer(warehouse, "C3")};
for (Thread t : producers) t.start();
for (Thread t : consumers) t.start();
Thread.sleep(5000); // 運行 5 秒
for (Thread t : producers) ((Producer)t).shutdown();
for (Thread t : consumers) ((Consumer)t).shutdown();
}
}
| 技術點 | 說明 |
|---|---|
| 環形陣列 | 避免資料搬移,front/rear 取模運算 |
| 滿/空區分 | 犧牲一格空間:(rear+1)%cap == front 為滿 |
| synchronized | 保護共享狀態,配合 wait/notify |
| while 而非 if | 防止虛假喚醒 |
| notifyAll | 喚醒所有等待者,避免單喚醒導致死鎖 |
| volatile running | 跨執行緒可見性,優雅關閉 |
| interrupt() | 打斷 sleep/wait,加速關閉 |
BlockingQueue (ArrayBlockingQueue/LinkedBlockingQueue) - 線程安全、內建阻塞、無需手寫 wait/notifyCompletableFuture / ExecutorService - 任務導向編程