A,執行緒 B 僅列印 B,各 10 次,輸出 ABABAB...。A/B/C,各 100 次,輸出 ABCABC...。核心考點:等待/通知機制(wait()/notify()/notifyAll())、共享狀態協調、避免虛假喚醒(用 while 而非 if)。
public class PrintAB {
public static void main(String[] args) {
final Printer printer = new Printer();
new Thread(() -> { for (int i = 0; i < 10; i++) printer.printA(); }, "Thread-A").start();
new Thread(() -> { for (int i = 0; i < 10; i++) printer.printB(); }, "Thread-B").start();
}
}
class Printer {
private boolean flag = true; // true 輪到 A,false 輪到 B
public synchronized void printA() {
while (!flag) { // 虛假喚醒防護
try { this.wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
}
System.out.print("A");
flag = false;
this.notify(); // 喚醒 B
}
public synchronized void printB() {
while (flag) {
try { this.wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
}
System.out.print("B");
flag = true;
this.notify(); // 喚醒 A
}
}
synchronized 確保檢查旗標與修改旗標的原子性。while (!flag) 防止虛假喚醒(JVM 允許無通知自動喚醒)。notify() 單喚醒足夠,因只有另一個執行緒在等待。class PrinterABC {
private int state = 0; // 0:A, 1:B, 2:C
public synchronized void printA() {
while (state != 0) { wait(); }
System.out.print("A");
state = 1;
notifyAll(); // 必須喚醒所有,因 B/C 皆可能在等
}
public synchronized void printB() {
while (state != 1) { wait(); }
System.out.print("B");
state = 2;
notifyAll();
}
public synchronized void printC() {
while (state != 2) { wait(); }
System.out.print("C");
state = 0;
notifyAll();
}
}
notifyAll()?三執行緒時,喚醒單一執行緒可能喚醒「非目標」執行緒(如 A 執行完喚醒 C,C 發現 state!=1 繼續等待,導致 B 永遠不被喚醒)。notifyAll() 確保正確執行緒最終被喚醒。
class JucPrinter {
private final ReentrantLock lock = new ReentrantLock();
private final Condition aCon = lock.newCondition();
private final Condition bCon = lock.newCondition();
private final Condition cCon = lock.newCondition();
private int state = 0;
public void printA() {
lock.lock();
try {
while (state != 0) aCon.await();
System.out.print("A");
state = 1;
bCon.signal();
} finally { lock.unlock(); }
}
// printB/printC 類似,signal 目標 Condition
}
優勢:精準喚醒(signal() 對應特定 Condition)、可中斷等待(awaitInterruptibly())、公平鎖選項、多條件變數語義清晰。
class CyclicPrinter {
private final int n; // 執行緒數
private int current = 0;
private final ReentrantLock lock = new ReentrantLock();
private final Condition[] conditions;
public CyclicPrinter(int n) {
this.n = n;
conditions = new Condition[n];
for (int i = 0; i < n; i++) conditions[i] = lock.newCondition();
}
public void print(int id, String text, int times) {
for (int i = 0; i < times; i++) {
lock.lock();
try {
while (current != id) conditions[id].await();
System.out.print(text);
current = (current + 1) % n;
conditions[current].signal();
} catch (InterruptedException e) { Thread.currentThread().interrupt(); break; }
finally { lock.unlock(); }
}
}
}
while + wait/notify 正確模板。notify vs notifyAll 適用場景。synchronized 與 ReentrantLock+Condition 優劣,推薦 JUC 寫法。