需求:線程 A 打印「A」,線程 B 打印「B」,各 10 次,輸出 ABABAB...。核心在於共享狀態標誌位 + wait/notify 協作。
public class PrintAB {
public static void main(String[] args) {
PrintService service = new PrintService();
new Thread(() -> { for (int i = 0; i < 10; i++) service.printA(); }, "Thread-A").start();
new Thread(() -> { for (int i = 0; i < 10; i++) service.printB(); }, "Thread-B").start();
}
}
class PrintService {
private boolean flag = true; // true 輪到 A,false 輪到 B
public synchronized void printA() {
while (!flag) wait(); // 非本輪等待
System.out.print("A");
flag = false;
notify(); // 喚醒 B
}
public synchronized void printB() {
while (flag) wait(); // 非本輪等待
System.out.print("B");
flag = true;
notify(); // 喚醒 A
}
}
擴展為 N 線程需維護「誰的回合」狀態,推薦使用 int turn 或 boolean[] 標記,配合 notifyAll() 避免虛假喚醒導致死鎖。
class PrintABC {
private int turn = 0; // 0:A, 1:B, 2:C
public synchronized void printA() {
while (turn != 0) wait();
System.out.print("A");
turn = 1;
notifyAll();
}
public synchronized void printB() {
while (turn != 1) wait();
System.out.print("B");
turn = 2;
notifyAll();
}
public synchronized void printC() {
while (turn != 2) wait();
System.out.print("C");
turn = 0;
notifyAll();
}
}
利用 ReentrantLock + Condition 替代 synchronized,支援動態線程數、可配置輪次,代碼更清晰、擴展性更強:
class CyclicPrinter {
private final int threadCount;
private final Lock lock = new ReentrantLock();
private final Condition[] conditions;
private int current = 0;
public CyclicPrinter(int n) {
this.threadCount = n;
this.conditions = new Condition[n];
for (int i = 0; i < n; i++) conditions[i] = lock.newCondition();
}
public void print(int id, String content, int rounds) {
for (int i = 0; i < rounds; i++) {
lock.lock();
try {
while (current != id) conditions[id].await();
System.out.print(content);
current = (current + 1) % threadCount;
conditions[current].signal();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
}
}
}
PrintService),業務線程僅調用。while 迴圈檢查條件防虛假喚醒;notifyAll 確保多線程場景無遺漏。掌握「共享狀態 + 等待通知」模式,即可輕鬆應對各類線程有序協作問題。