目录
- 一、并发基础:餐厅后厨的协作艺术
- 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 {
@Override
public 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 线程池》
💬互动话题:第一要有志,第二要有识,第三要有恒
🏷️温馨提示:我是[随缘而动,随遇而安], 一个喜欢用生活案例讲技术的开发者。如果觉得有帮助,点赞关注不迷路🌟