第七十三篇 从电影院售票到停车场计数:生活场景解析Java原子类精髓

目录

    • 一、原子类基础:电影院售票系统
      • 1.1 传统售票的并发问题
      • 1.2 原子类解决方案
    • 二、原子类家族:超市收银系统
      • 2.1 基础类型原子类
      • 2.2 数组类型原子类
    • 三、CAS机制深度解析:停车场管理系统
      • 3.1 CAS工作原理
      • 3.2 车位计数器实现
    • 四、高性能实践:银行账户系统
      • 4.1 账户余额更新
      • 4.2 性能对比测试
    • 五、原子类进阶:电影院选座系统
      • 5.1 座位状态管理
      • 5.2 批量更新优化

想象电影院售票处:多个窗口同时售票却不会售出重复座位;停车场入口自动计数系统实时更新车位状态------这正是Java原子类的完美生活映射。本文将用日常场景揭秘高并发环境下的无锁编程奥秘。

一、原子类基础:电影院售票系统

1.1 传统售票的并发问题

java 复制代码
// 非原子操作导致超卖
public class TicketCounter {
    private int totalTickets = 100;
    
    public void sellTicket() {
        if(totalTickets > 0) {
            // 此处可能被其他线程中断
            totalTickets--; 
            System.out.println("售出1张票,剩余:" + totalTickets);
        }
    }
}

1.2 原子类解决方案

java 复制代码
public class AtomicTicketCounter {
    private final AtomicInteger tickets = new AtomicInteger(100);
    
    public void safeSellTicket() {
        int current;
        do {
            current = tickets.get();
            if(current <= 0) {
                System.out.println("票已售罄");
                return;
            }
        } while(!tickets.compareAndSet(current, current - 1));
        
        System.out.println("安全售出,剩余:" + tickets.get());
    }
}

二、原子类家族:超市收银系统

2.1 基础类型原子类

java 复制代码
// 收银台计数器
AtomicLong dailySales = new AtomicLong(0); 

// 每笔交易更新
void processTransaction(double amount) {
    // 累加销售额
    dailySales.addAndGet((long)(amount * 100));
    
    // 更新最高单笔交易
    AtomicReference<Double> maxTransaction = new AtomicReference<>(0.0);
    maxTransaction.accumulateAndGet(amount, Math::max);
}

2.2 数组类型原子类

java 复制代码
// 货架商品库存
AtomicIntegerArray shelfStock = new AtomicIntegerArray(10); 

// 补充第3号货架商品
void restockShelf(int shelfId, int quantity) {
    shelfStock.addAndGet(shelfId, quantity);
}

// 顾客购买商品
boolean purchaseItem(int shelfId) {
    int current;
    do {
        current = shelfStock.get(shelfId);
        if(current <= 0) return false;
    } while(!shelfStock.compareAndSet(shelfId, current, current-1));
    
    return true;
}

三、CAS机制深度解析:停车场管理系统

3.1 CAS工作原理

是 否 读取当前值 计算新值 当前值是否未变? 更新成功 重试操作

3.2 车位计数器实现

java 复制代码
public class ParkingLot {
    private final AtomicInteger availableSpots;
    private final int totalSpots;
    
    public ParkingLot(int capacity) {
        this.totalSpots = capacity;
        this.availableSpots = new AtomicInteger(capacity);
    }
    
    // 车辆进入
    public boolean carEnter() {
        int current;
        do {
            current = availableSpots.get();
            if(current <= 0) return false;
        } while(!availableSpots.compareAndSet(current, current - 1));
        
        updateDisplay();
        return true;
    }
    
    // 车辆离开
    public void carExit() {
        availableSpots.incrementAndGet();
        updateDisplay();
    }
    
    private void updateDisplay() {
        System.out.println("当前车位: " + availableSpots + "/" + totalSpots);
    }
}

四、高性能实践:银行账户系统

4.1 账户余额更新

java 复制代码
public class BankAccount {
    private final AtomicLong balance;
    
    public BankAccount(long initial) {
        this.balance = new AtomicLong(initial);
    }
    
    // 无锁存款
    public void deposit(long amount) {
        balance.addAndGet(amount);
    }
    
    // 安全取款(避免透支)
    public boolean withdraw(long amount) {
        long current;
        do {
            current = balance.get();
            if(current < amount) return false;
        } while(!balance.compareAndSet(current, current - amount));
        
        return true;
    }
    
    // 转账操作
    public boolean transferTo(BankAccount target, long amount) {
        if(this.withdraw(amount)) {
            target.deposit(amount);
            return true;
        }
        return false;
    }
}

4.2 性能对比测试

操作方式 100万次操作耗时 适用场景
synchronized 450ms 复杂事务处理
ReentrantLock 380ms 需要高级功能的场景
AtomicLong 120ms 简单计数器场景

五、原子类进阶:电影院选座系统

5.1 座位状态管理

java 复制代码
public class SeatManager {
    // 使用AtomicReference数组管理座位状态
    private final AtomicReference<SeatStatus>[] seats;
    
    public SeatManager(int capacity) {
        seats = new AtomicReference[capacity];
        // 初始化所有座位为空闲
        Arrays.fill(seats, new AtomicReference<>(SeatStatus.AVAILABLE));
    }
    
    // 预订座位
    public boolean bookSeat(int seatId) {
        return seats[seatId].compareAndSet(SeatStatus.AVAILABLE, SeatStatus.OCCUPIED);
    }
    
    // 释放座位
    public void releaseSeat(int seatId) {
        seats[seatId].set(SeatStatus.AVAILABLE);
    }
    
    enum SeatStatus { AVAILABLE, OCCUPIED }
}

5.2 批量更新优化

java 复制代码
// 使用LongAdder优化高频计数器
public class TicketCounter {
    private final LongAdder totalSales = new LongAdder();
    private final LongAdder vipSales = new LongAdder();
    
    public void sellTicket(boolean isVip) {
        totalSales.increment();
        if(isVip) vipSales.increment();
    }
    
    // 生成报表
    public void generateReport() {
        System.out.println("总售票: " + totalSales.sum());
        System.out.println("VIP票: " + vipSales.sum());
    }
}

🎯下期预告 :《Java 并发容器》
💬互动话题 :不深思则不能造于道。不深思而得者,其得易失
🏷️温馨提示 :我是[随缘而动,随遇而安], 一个喜欢用生活案例讲技术的开发者。如果觉得有帮助,点赞关注不迷路🌟

相关推荐
Mikhail_G2 分钟前
Python应用函数调用(二)
大数据·运维·开发语言·python·数据分析
lanfufu4 分钟前
记一次诡异的线上异常赋值排查:代码没错,结果不对
java·jvm·后端
编程轨迹9 分钟前
如何在 Java 中实现 PDF 与 TIFF 格式互转
后端
编程轨迹9 分钟前
面试官:你知道如何在 Java 中创建对话框吗
后端
编程轨迹20 分钟前
深入理解 Java 中的信号机制
后端
夕颜11124 分钟前
让 cursor 教我用 cursor 的隐藏技能
后端·trae
橘子青衫32 分钟前
Java并发编程利器:CyclicBarrier与CountDownLatch解析
java·后端·性能优化
编程轨迹34 分钟前
如何在 Java 中整合 HTML 文档
后端
编程轨迹34 分钟前
如何在 Java 中将 XLS 转换为 XLSX
后端
天天摸鱼的java工程师44 分钟前
高考放榜夜,系统别崩!聊聊查分系统怎么设计,三张表足以?
java·后端·mysql