目錄
- 一、并發基礎:餐廳后廚的協作藝術
- 1.1 廚師與線程(Thread)
- 1.2 共享資源競爭:唯一的炒鍋
- 1.3 線程狀態轉換:廚師工作流
- 二、線程同步:電影院選座中的鎖機制
- 2.1 同步鎖(synchronized):選座系統
- 2.2 顯式鎖(ReentrantLock):VIP選座通道
- 三、線程協作:咖啡廳的點單取餐系統
- 3.1 生產者-消費者模式
- 3.2 CountDownLatch:旅行團集合點
- 四、并發工具進階:超市收銀系統
- 4.1 線程池(ExecutorService):收銀通道管理
- 4.2 ConcurrentHashMap:實時庫存系統
- 五、避坑指南:并發編程常見陷阱
- 5.1 死鎖場景:十字路口的四輛車
- 5.2 線程饑餓:永遠輪不到的普通會員
- 5.3 內存可見性:過期的餐廳菜單
- 六、性能優化:電影院排片策略
- 6.1 鎖粒度控制
- 6.2 無鎖編程:原子類操作
- 結語:構建高效并發系統
想象一家繁忙的餐廳后廚:主廚指揮多個廚師同時處理訂單,服務員在取餐口等待出菜,新訂單不斷涌入——這正是Java并發編程的完美生活映射。本文將用你熟悉的日常場景,帶你掌握高并發系統的構建之道。
一、并發基礎:餐廳后廚的協作藝術
1.1 廚師與線程(Thread)
每個廚師就像一個線程:
// 廚師線程類
class ChefThread extends Thread {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "開始烹飪");// 模擬烹飪耗時try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }}
}// 啟動5個廚師線程
public static void main(String[] args) {for (int i=1; i<=5; i++) {new ChefThread().start();}
}
1.2 共享資源競爭:唯一的炒鍋
當多個廚師爭搶**同一個炒鍋(共享資源)**時:
// 共享炒鍋資源
class Wok {private boolean inUse = false;// 加鎖使用炒鍋public synchronized void use(String chefName) {if(inUse) return;inUse = true;System.out.println(chefName + "占用炒鍋");}
}
1.3 線程狀態轉換:廚師工作流
線程狀態 | 廚師狀態 | 觸發條件 |
---|---|---|
RUNNABLE | 正在切菜 | 獲取到食材 |
BLOCKED | 等待炒鍋 | 其他廚師占用炒鍋 |
WAITING | 等待服務員傳菜 | 菜品完成但服務員未就位 |
TIMED_WAITING | 定時查看烤箱 | 設置定時器監控烘焙進度 |
二、線程同步:電影院選座中的鎖機制
2.1 同步鎖(synchronized):選座系統
場景:多人同時在線選座,避免座位重復出售
class Cinema {private boolean[] seats = new boolean[100]; // 100個座位// 同步選座方法public synchronized boolean bookSeat(int seatNo) {if(!seats[seatNo]) {seats[seatNo] = true;System.out.println(Thread.currentThread().getName() + "成功預訂座位" + seatNo);return true;}return false;}
}
2.2 顯式鎖(ReentrantLock):VIP選座通道
場景:提供超時等待功能,避免無限期阻塞
private ReentrantLock lock = new ReentrantLock();public boolean vipBookSeat(int seatNo) {try {// 嘗試在1秒內獲取鎖if(lock.tryLock(1, TimeUnit.SECONDS)) {if(!seats[seatNo]) {seats[seatNo] = true;return true;}}} catch (InterruptedException e) {e.printStackTrace();} finally {if(lock.isHeldByCurrentThread()) {lock.unlock();}}return false;
}
三、線程協作:咖啡廳的點單取餐系統
3.1 生產者-消費者模式
場景:顧客(生產者)下單,咖啡師(消費者)制作
BlockingQueue<Order> orderQueue = new ArrayBlockingQueue<>(10);// 顧客下單
class Customer implements Runnable {public void run() {orderQueue.put(new Order()); // 隊列滿時阻塞}
}// 咖啡師制作
class Barista implements Runnable {public void run() {while(true) {Order order = orderQueue.take(); // 隊列空時阻塞makeCoffee(order);}}
}
3.2 CountDownLatch:旅行團集合點
場景:導游等待所有游客到齊才發車
CountDownLatch latch = new CountDownLatch(10); // 10人旅行團// 游客線程
class Tourist extends Thread {public void run() {System.out.println(getName() + "到達集合點");latch.countDown();}
}// 導游線程
class Guide extends Thread {public void run() {latch.await(); // 等待所有游客System.out.println("所有游客到齊,發車!");}
}
四、并發工具進階:超市收銀系統
4.1 線程池(ExecutorService):收銀通道管理
// 開放4個收銀通道
ExecutorService cashiers = Executors.newFixedThreadPool(4); // 顧客排隊結賬
for(int i=0; i<20; i++) {cashiers.execute(() -> {System.out.println("顧客在"+Thread.currentThread().getName()+"結賬");});
}cashiers.shutdown(); // 營業結束關閉收銀臺
4.2 ConcurrentHashMap:實時庫存系統
ConcurrentHashMap<String, Integer> inventory = new ConcurrentHashMap<>();// 多個收銀臺同時更新庫存
inventory.compute("可樂", (k, v) -> v == null ? -1 : v-1);
五、避坑指南:并發編程常見陷阱
5.1 死鎖場景:十字路口的四輛車
條件:四個方向的車都等待對方先通行
解決方案:規定通行優先級(鎖排序)
5.2 線程饑餓:永遠輪不到的普通會員
現象:VIP會員總是優先辦理業務
修復:使用公平鎖(Fair Lock)
5.3 內存可見性:過期的餐廳菜單
// 錯誤示例:其他線程可能看不到menuChanged更新
boolean menuChanged = false; // 正確做法:使用volatile保證可見性
volatile boolean menuChanged = true;
六、性能優化:電影院排片策略
6.1 鎖粒度控制
// 粗粒度鎖:鎖整個影廳(性能差)
public synchronized void bookSeats(List<Integer> seats) {...}// 細粒度鎖:只鎖選定座位(推薦)
public void bookSeats(List<Integer> seats) {for (int seat : seats) {synchronized (seatLocks[seat]) {// 處理單個座位}}
}
6.2 無鎖編程:原子類操作
AtomicInteger availableTickets = new AtomicInteger(100);// 多個窗口同時售票
public boolean sellTicket() {int current = availableTickets.get();if(current > 0) {return availableTickets.compareAndSet(current, current-1);}return false;
}
結語:構建高效并發系統
Java并發編程如同管理繁忙的餐廳后廚:
- 合理分工:使用線程池控制工作線程數量
- 資源協調:通過鎖機制避免資源沖突
- 流程優化:利用阻塞隊列實現生產者-消費者模式
- 實時同步:采用原子操作保證數據一致性
掌握這些生活化的并發模式,你將能構建出如米其林餐廳后廚般高效運轉的Java應用系統。記住:優秀的并發程序不是沒有鎖,而是讓線程排隊時間最小化,協作效率最大化。
🎯下期預告:《Java 線程池》
💬互動話題:第一要有志,第二要有識,第三要有恒
🏷?溫馨提示:我是[隨緣而動,隨遇而安], 一個喜歡用生活案例講技術的開發者。如果覺得有幫助,點贊關注不迷路🌟