留学网站建设多少钱上海网站开发有限公司
你的回答(口语化,面试场景)
 面试官:你使用过哪些 Java 并发工具类?
 你:
 好的,我结合项目经验来说说常用的并发工具类:
- CountDownLatch
 
- 作用:等所有线程就绪后再触发任务,或主线程等待子线程完成。
 - 场景:压测时模拟高并发(比如100个请求同时发起)。
 - 代码示例:
CountDownLatch latch = new CountDownLatch(3); // 三个子线程执行任务 executor.submit(() -> { doWork(); latch.countDown(); }); latch.await(); // 主线程阻塞等待 System.out.println("所有任务完成"); 
- CyclicBarrier
 
- 作用:让一组线程互相等待,达到屏障点后统一执行后续逻辑。
 - 场景:多线程分阶段处理数据(比如先各自加载数据,再统一合并)。
 - 代码示例:
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("全部就绪!")); executor.submit(() -> { loadData(); barrier.await(); // 等待其他线程 mergeData(); }); 
- Semaphore
 
- 作用:控制并发线程数(比如限流)。
 - 场景:数据库连接池限制、接口限流(防止瞬时流量打满系统)。
 - 代码示例:
Semaphore semaphore = new Semaphore(5); // 允许5个线程同时执行 if (semaphore.tryAcquire(2, TimeUnit.SECONDS)) { // 超时等待 try { accessDB(); } finally { semaphore.release(); } } 
- ReentrantLock 和 StampedLock
 
- ReentrantLock: 
- 可替代 
synchronized,支持公平锁、可中断锁。 - 场景:需要尝试获取锁(
tryLock())或避免死锁(比如支付超时回滚)。 
 - 可替代 
 - StampedLock: 
- 读多写少场景优化,通过“乐观读”减少锁竞争。
 - 场景:高频读、低频写的缓存(比如商品库存缓存)。
 
 
- 原子类(AtomicInteger 等)
 
- 作用:无锁线程安全操作(基于 CAS)。
 - 场景:计数器(比如统计接口调用次数)、状态标志。
AtomicInteger counter = new AtomicInteger(0); counter.incrementAndGet(); // 线程安全自增 
- Future 和 CompletableFuture
 
- Future:异步获取任务结果(需配合线程池)。
 - CompletableFuture: 
- 支持链式调用、组合多个异步任务(如 
thenApply()、allOf())。 - 场景:微服务并行调用(比如同时查询订单和用户信息)。
 
 - 支持链式调用、组合多个异步任务(如 
 
- 线程池工具类(Executors)
 
- 常用线程池: 
newFixedThreadPool:固定线程数,适用于稳定负载。newCachedThreadPool:弹性线程数,适合短时异步任务。newScheduledThreadPool:定时任务调度(替代 Timer)。
 - 注意:阿里规约建议手动创建 
ThreadPoolExecutor,避免资源耗尽风险。 
- 并发集合(ConcurrentHashMap、CopyOnWriteArrayList)
 
- ConcurrentHashMap: 
- 分段锁(JDK7)或 CAS + synchronized(JDK8),高并发下替代 HashMap。
 - 场景:全局缓存(比如电商首页类目数据)。
 
 - CopyOnWriteArrayList: 
- 写时复制,读多写少场景(比如监听器列表)。
 
 
预测面试官可能的追问及回答
 追问1:CountDownLatch 和 CyclicBarrier 有什么区别?
 回答:
- 触发机制: 
CountDownLatch通过countDown()减计数,await()阻塞直到计数归零,一次性使用。CyclicBarrier通过await()等待线程数达标后触发回调,可重复使用(reset())。
 - 场景: 
CountDownLatch主等子,CyclicBarrier子等子。
 
追问2:ReentrantLock 和 synchronized 怎么选?
 回答:
- 优先 
synchronized:代码简洁,JVM自动管理锁。 - 需要高级功能时用 
ReentrantLock:比如尝试获取锁(tryLock)、公平锁、可中断锁。 
知识框架与底层原理补充
-  
并发工具分类
| 类别 | 工具类 | 解决的核心问题 |
|--------------------|------------------------------------------|-------------------------------|
| 线程协作 |CountDownLatch,CyclicBarrier| 多线程步调协调 |
| 资源控制 |Semaphore, 线程池 | 限制并发资源使用 |
| 锁机制 |ReentrantLock,StampedLock| 显式控制同步与互斥 |
| 线程安全容器 |ConcurrentHashMap,CopyOnWriteArrayList| 高并发下数据安全访问 |
| 异步任务 |Future,CompletableFuture| 非阻塞任务编排与结果获取 | -  
底层原理
 
- AQS(AbstractQueuedSynchronizer): 
ReentrantLock、Semaphore、CountDownLatch均基于 AQS 实现,通过state变量和 CLH 队列管理线程阻塞与唤醒。
 - CAS(Compare-And-Swap): 
- 原子类(如 
AtomicInteger)和ConcurrentHashMap的线程安全操作依赖 CAS,避免锁竞争。 
 - 原子类(如 
 - 写时复制(Copy-On-Write): 
CopyOnWriteArrayList在写入时复制整个数组,保证读操作无锁,适合读多写极少场景。
 
- 最佳实践
 
- 避免死锁: 
- 锁顺序一致、超时释放(
tryLock)、使用并发集合替代手动同步。 
 - 锁顺序一致、超时释放(
 - 性能优化: 
- 读多写少用 
StampedLock,写多用ReentrantLock。 - 短任务用 
CompletableFuture而非阻塞线程池。 
 - 读多写少用 
 - 线程池参数: 
- 根据任务类型(CPU 密集型 vs IO 密集型)设置核心线程数(CPU 数 +1 或 2*CPU 数)。
 
 
- 高频面试题扩展
 
ConcurrentHashMap在 JDK7 和 JDK8 的区别?- JDK7:分段锁(Segment),锁粒度粗。
 - JDK8:CAS + synchronized 锁单个 Node,粒度更细。
 
CompletableFuture的默认线程池问题?- 默认使用 
ForkJoinPool.commonPool(),建议自定义线程池避免业务阻塞公共池。 
- 默认使用 
 
通过理解这些工具类的设计意图和底层机制,你可以在面试中展现出对高并发场景的深刻掌控力!
