java.util.concurrent.locks.Lock 接口提供比 synchronized 更靈活的同步控制:支持可中斷獲取鎖(lockInterruptibly())、超時獲取(tryLock(timeout))、公平/非公平策略、條件變量(newCondition())。ReentrantLock 是其標準實現,內部基於 AQS(AbstractQueuedSynchronizer)隊列同步器構建。
private final Lock lock = new ReentrantLock(); // 非公平鎖
// private final Lock lock = new ReentrantLock(true); // 公平鎖
public void run() {
while (true) {
lock.lock(); // 必須在 try 外獲取,確保 finally 能釋放
try {
if (tickets > 0) {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " 出售第 " + tickets-- + " 張票");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock(); // 保證釋放
}
}
}
死鎖四必要條件:互斥、請求與保持、不剝佔、循環等待。典型場景為多線程以不同順序獲取多把鎖。
// 死鎖復現:線程 1 鎖 A→B,線程 2 鎖 B→A
static final Object lockA = new Object(), lockB = new Object();
new Thread(() -> {
synchronized (lockA) {
sleep(100);
synchronized (lockB) { /* ... */ }
}
}).start();
new Thread(() -> {
synchronized (lockB) {
sleep(100);
synchronized (lockA) { /* ... */ }
}
}).start();
排查手段:jstack PID 生成線程快照,搜尋 "Found one Java-level deadlock";或使用 JConsole/VisualVM 圖形化檢測。預防原則:統一鎖獲取順序、使用 tryLock(timeout) 避免無限等待、縮小同步塊範圍。
通過構造器注入同一 Student 實例,解決「各線程操作不同對象」導致的數據不一致。
「設置姓名+年齡」、「讀取姓名+年齡」屬於複合操作,需同步。關鍵點:生產/消費線程必須使用同一把鎖(此處為共享對象 s)。
引入 boolean flag 標記缓衝區狀態:
// 生產者
synchronized (s) {
while (s.flag) s.wait(); // 滿倉等待
s.setData(...);
s.flag = true;
s.notify(); // 喚醒消費者
}
// 消費者
synchronized (s) {
while (!s.flag) s.wait(); // 空倉等待
s.getData();
s.flag = false;
s.notify(); // 喚醒生產者
}
核心規則:wait/notify/notifyAll 必須在同步塊內調用,且由鎖對象調用;wait() 釋放鎖並進入 WAITING 狀態,被喚醒後重新競爭鎖,從 wait() 之後繼續執行。
將 set/get 方法聲明為 synchronized,內部自管 wait/notify,調用者無需關心同步細節,體現「高內聚、低耦合」。
public class Student {
private String name; private int age; private boolean flag = false;
public synchronized void set(String name, int age) {
while (flag) { try { wait(); } catch (InterruptedException e) {} }
this.name = name; this.age = age; flag = true; notify();
}
public synchronized void get() {
while (!flag) { try { wait(); } catch (InterruptedException e) {} }
System.out.println(name + "---" + age); flag = false; notify();
}
}

start())wait()/join())/ TIMED_WAITING(sleep()/wait(timeout))run() 結束或異常拋出)ThreadGroup group = new ThreadGroup("BatchGroup");
group.setDaemon(true); // 整組設置為守護線程
new Thread(group, task, "Worker-1").start();
new Thread(group, task, "Worker-2").start();
// 批量中斷
group.interrupt();
// 遞歸枚舉
Thread[] list = new Thread[group.activeCount()];
group.enumerate(list);
| 工廠方法 | 特性 | 適用場景 |
|---|---|---|
newFixedThreadPool(n) | 固定核心數,無界隊列 | 長期任務、控制並發度 |
newCachedThreadPool() | 核心 0,最大 Integer.MAX_VALUE,60s 空閒回收 | 大量短期異步任務 |
newSingleThreadExecutor() | 單線程串行,保證順序 | 順序執行、UI 事件分發 |
newScheduledThreadPool(n) | 支持定時/周期任務 | 定時器替代品 |
ExecutorService pool = Executors.newFixedThreadPool(2);
Future f1 = pool.submit(() -> { int sum=0; for(int i=1;i<=100;i++) sum+=i; return sum; });
Future f2 = pool.submit(new Callable() { ... }); // JDK 7 匿名內部類寫法
System.out.println(f1.get() + ", " + f2.get()); // 阻塞獲取結果
pool.shutdown(); // 拒絕新任務,等待現有任務完成
// pool.shutdownNow(); // 嘗試中斷執行中任務
Callable 支持返回值與拋出受檢異常,配合 Future 實現異步計算結果獲取。Future.get() 會阻塞直到任務完成;可用 future.cancel(true) 嘗試取消。
Timer timer = new Timer();
// 延遲 3s 執行一次
timer.schedule(new TimerTask() {
public void run() { System.out.println("Boom!"); timer.cancel(); }
}, 3000);
// 3s 後首次,之後每 2s 執行
timer.schedule(new TimerTask() {
public void run() { System.out.println("Periodic"); }
}, 3000, 2000);
// 指定時間點觸發
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date time = sdf.parse("2025-12-31 23:59:59");
timer.schedule(task, time);
注意:Timer 單線程串行,任務耗時長會延遲後續任務;生產環境建議使用 ScheduledThreadPoolExecutor 或 Quartz/Spring Task。
class DeleteFolderTask extends TimerTask {
public void run() {
deleteRecursively(new File("demo"));
}
void deleteRecursively(File dir) {
File[] files = dir.listFiles();
if (files != null) {
for (File f : files) {
if (f.isDirectory()) deleteRecursively(f);
else f.delete();
}
}
dir.delete();
}
}
start() 啟動新線程由 JVM 調用 run();直接調用 run() 為主線程同步執行sleep 不釋放鎖、指定時間;wait 釋放鎖、可無參無限等待、需同步塊內調用
// 餓漢式:類加載即創建,線程安全,無延遲加載
public class HungrySingleton {
private static final HungrySingleton INSTANCE = new HungrySingleton();
private HungrySingleton() {}
public static HungrySingleton getInstance() { return INSTANCE; }
}
// 懶漢式(雙重檢查鎖 DCL):延遲加載 + 線程安全
public class LazySingleton {
private static volatile LazySingleton instance; // volatile 禁止指令重排
private LazySingleton() {}
public static LazySingleton getInstance() {
if (instance == null) {
synchronized (LazySingleton.class) {
if (instance == null) instance = new LazySingleton();
}
}
return instance;
}
}
JDK Runtime.getRuntime() 採用餓漢式單例,提供 exec() 執行系統命令(如 shutdown -s -t 10000 定時關機,shutdown -a 取消)。