在高并发系统开发中,Java并发编程是每个后端工程师必须掌握的核心技能之一。本文将从基础到进阶,带你全面了解线程池、锁机制、CAS与AQS原理,并通过实际代码案例帮助你理解如何在项目中应用这些技术。
线程池是一种基于“池化”思想管理线程的技术,它可以复用线程资源,减少线程频繁创建销毁带来的性能损耗。
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.submit(() -> {
System.out.println("执行任务");
});
executor.shutdown();
推荐使用
ThreadPoolTaskExecutor
代替Executors
以避免OOM。
public class SyncDemo {
private int count = 0;
public synchronized void increment() {
count++;
}
}
private volatile boolean running = true;
public void stop() {
running = false;
}
CAS(Compare and Swap)是一种无锁算法,在硬件层面上提供了原子操作的支持。
AtomicInteger atomicInt = new AtomicInteger(0);
atomicInt.compareAndSet(0, 1);
AQS是JUC包下许多并发工具的基础框架,如ReentrantLock、Semaphore、CountDownLatch都基于AQS实现。
public class MyLock extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int arg) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
setState(0);
setExclusiveOwnerThread(null);
return true;
}
public void lock() { acquire(1); }
public void unlock() { release(1); }
}
倒计时门闩,用于等待多个线程完成后再继续执行。
CountDownLatch latch = new CountDownLatch(3);
new Thread(() -> {
System.out.println("任务1完成");
latch.countDown();
}).start();
latch.await();
System.out.println("所有任务已完成");
循环屏障,适用于多线程协同计算场景
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("所有线程已就位,开始执行...");
});
for (int i = 0; i < 3; i++) {
new Thread(() -> {
try {
barrier.await();
System.out.println(Thread.currentThread().getName() + " 执行完毕");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
信号量控制资源访问数量
Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " 正在使用资源");
Thread.sleep(1000);
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
电商平台秒杀系统中需要防止超卖现象,要求高并发情况下库存准确且不能为负。
@Service
public class StockService {
@Autowired
private RedisTemplate redisTemplate;
private ExecutorService executor = Executors.newFixedThreadPool(10);
public void deductStock(String productId) {
String stockKey = "stock:" + productId;
String script = "if redis.call('get', KEYS[1]) > 0 then return redis.call('decr', KEYS[1]) else return -1 end";
DefaultRedisScript redisScript = new DefaultRedisScript<>();
redisScript.setScriptText(script);
redisScript.setResultType(Long.class);
Long result = redisTemplate.execute(redisScript, List.of(stockKey));
if (result == null || result < 0) {
throw new RuntimeException("库存不足");
}
}
public void asyncDeductStock(String productId) {
executor.submit(() -> {
deductStock(productId);
});
}
}
本文从并发基础讲到高级并发编程技巧,涵盖了线程池、锁优化、CAS、AQS、并发工具类等多个关键点,并通过真实电商秒杀库存扣减案例展示了如何在项目中落地这些技术。建议读者结合源码深入理解每种机制背后的设计哲学,这对提升架构能力有很大帮助。