当前位置: 首页 > news >正文

深度剖析Java高并发:从线程池到CAS原理,阿里面试必问系列

引言

高并发是Java后端开发的核心能力,也是大厂面试的重灾区。本文将从线程池核心原理、CAS无锁机制、Synchronized优化、JUC并发工具类四个维度,深入剖析Java高并发的底层逻辑。


一、线程池核心原理

1.1 线程池为什么要用

直接创建线程的问题:

// 每次请求都创建新线程for(inti=0;i<1000;i++){newThread(()->{// 业务逻辑}).start();}

问题:

  • 线程创建和销毁开销大
  • 大量线程竞争CPU资源
  • 线程数量不可控

1.2 线程池工作原理

// 线程池核心参数publicThreadPoolExecutor(intcorePoolSize,// 核心线程数intmaximumPoolSize,// 最大线程数longkeepAliveTime,// 空闲线程存活时间TimeUnitunit,// 时间单位BlockingQueue<Runnable>workQueue,// 任务队列ThreadFactorythreadFactory,// 线程工厂RejectedExecutionHandlerhandler// 拒绝策略)

线程池执行流程:

任务进来 ↓ corePoolSize未满?→ 创建核心线程执行 ↓ (是) 核心线程满了吗? ↓ (否) workQueue未满?→ 任务加入队列等待 ↓ (是) maximumPoolSize未满?→ 创建临时线程执行 ↓ (是) 执行拒绝策略

1.3 七大参数详解

参数含义设置建议
corePoolSize核心线程数CPU密集型:CPU核数+1;IO密集型:CPU核数×2
maximumPoolSize最大线程数corePoolSize × 2
keepAliveTime空闲存活时间默认10ms
workQueue任务队列LinkedBlockingQueue/SynchronousQueue
threadFactory线程工厂自定义线程名便于排查
handler拒绝策略AbortPolicy/CallerRunsPolicy

1.4 阿里面试题:线程池大小怎么设置?

// CPU密集型任务intcorePoolSize=Runtime.getRuntime().availableProcessors()+1;// IO密集型任务(经验公式)intcorePoolSize=Runtime.getRuntime().availableProcessors()*2;// 或者更精确的计算intcorePoolSize=Runtime.getRuntime().availableProcessors()/(1-阻塞系数)// 阻塞系数通常取0.8~0.9

二、CAS无锁机制

2.1 CAS是什么

CAS(Compare And Swap)是一种无锁算法,它包含三个操作数:

  • 内存位置 V
  • 预期原值 A
  • 新值 B
// CAS语义:只有当V的值等于A时,才用B去更新V// 否则什么都不做,返回V当前值

2.2 Java中CAS的实现

// AtomicInteger源码分析publicclassAtomicIntegerextendsNumber{privatestaticfinallongserialVersionUID=...;// 使用Unsafe类的CAS操作privatevolatileintvalue;publicfinalbooleancompareAndSwap(intexpectedValue,intnewValue){returnunsafe.compareAndSwapInt(this,valueOffset,expectedValue,newValue);}// 乐观锁实现publicfinalintincrementAndGet(){for(;;){intcurrent=get();intnext=current+1;if(compareAndSwap(current,next)){returnnext;}}}}

2.3 CAS的三大问题

问题1:ABA问题

// 线程1读取A,线程2将A改成B又改回A,线程1的CAS仍会成功// 解决:使用AtomicStampedReference增加版本号AtomicStampedReference<Integer>ref=newAtomicStampedReference<>(1,0);ref.compareAndSet(1,2,0,1);// 带版本号的CAS

问题2:自旋开销大

// 如果CAS失败,会一直自旋,消耗CPU// 解决:限制自旋次数,或使用LongAdderLongAddercounter=newLongAdder();counter.increment();// 分散热点,优于AtomicLong

问题3:只能保证一个变量原子性

// 多个变量需要原子操作怎么办?// 解决:使用AtomicReferenceAtomicReference<User>userRef=newAtomicReference<>();userRef.compareAndSet(oldUser,newUser);

三、Synchronized优化

3.1 synchronized锁升级路径

无锁 → 偏向锁 → 轻量级锁 → 重量级锁
锁类型场景升级条件
偏向锁单线程访问无竞争
轻量级锁多线程轻度竞争短时间自旋
重量级锁多线程激烈竞争自旋超过阈值

3.2 锁消除

publicvoidmethod(){// JIT编译时发现这个StringBuffer不会逃逸出方法外// 消除synchronized,直接拼接StringBuffersb=newStringBuffer();sb.append("a").append("b");// 实际上没有锁的开销}

3.3 锁粗化

// 连续加锁操作JIT会合并StringBuffersb=newStringBuffer();synchronized(sb){sb.append("a");}synchronized(sb){sb.append("b");}// JIT优化为:synchronized(sb){sb.append("a");sb.append("b");}

四、JUC并发工具类

4.1 CountDownLatch门闩

// 场景:等待多个线程执行完毕再执行主线程CountDownLatchlatch=newCountDownLatch(3);newThread(()->{// 任务1latch.countDown();}).start();newThread(()->{// 任务2latch.countDown();}).start();latch.await();// 阻塞直到countDown()被调用3次System.out.println("所有任务完成");

4.2 CyclicBarrier循环栅栏

// 场景:多个线程互相等待,全部到达后再执行CyclicBarrierbarrier=newCyclicBarrier(3,()->{System.out.println("所有人都到了,开始执行任务");});for(inti=0;i<3;i++){newThread(()->{// 准备任务barrier.await();// 等待其他人// 执行任务}).start();}

4.3 Semaphore信号量

// 场景:控制同时访问资源的线程数Semaphoresemaphore=newSemaphore(3);for(inti=0;i<10;i++){newThread(()->{try{semaphore.acquire();// 获取许可证// 访问共享资源(数据库连接池等)semaphore.release();// 释放许可证}catch(InterruptedExceptione){e.printStackTrace();}}).start();}

总结

知识点面试重点
线程池7大参数、执行流程、拒绝策略
CAS原理、ABA问题、LongAdder
Synchronized锁升级、锁消除、锁粗化
JUC工具CountDownLatch/CyclicBarrier/Semaphore

核心口诀:线程池控资源,CAS乐观无阻塞,Synchronized看升级,JUC工具解并发。

http://www.jsqmd.com/news/700166/

相关文章:

  • 技术方案:VRM4U与LiveLinkFace实时面部捕捉集成方案
  • 企业如何用OA系统提升办公效率?3步实现协作升级的实战指南
  • 【20年嵌入式老兵亲授】:用纯C手写Flash-aware KV缓存,让Qwen-1.5B在STM32H7上首帧推理≤89ms
  • 完全掌握Bebas Neue:从开源字体到专业设计实战应用
  • 每天学一个算法--回溯算法(Backtracking)
  • ComfyUI IPAdapter Plus:如何用一张图片重塑AI生成的艺术世界?
  • 抖音下载器完整指南:如何轻松下载无水印视频和直播内容
  • 从一次‘Failed to read artifact descriptor’报错,聊聊Maven依赖解析的完整链路与私服配置避坑
  • 医疗器械质量管理体系信息系统的详细设计
  • Realistic Vision V5.1写实人像生成实战:商业产品代言图AI制作全流程
  • 塑胶行业品牌曝光平台推荐 - 华旭传媒
  • 深度解析:如何用UE Viewer高效处理虚幻引擎1-4代游戏资源
  • Spring Cloud微服务架构详解:从服务注册到配置中心,阿里面试核心知识点
  • 国产时频测试仪器的破局之路:从“时间守门人”到产业赋能者
  • [T.4.5] 实验课/团队项目:团队代码管理准备-Ver.5-final-final-ffffffinal最终版真的绝对不再改了!!(2)_1
  • FormKit深度解析:基于Vue ue 3的声明式表单框架实战指南
  • 如何在Blender中轻松导入导出3MF文件:3D打印工作流终极指南
  • 终极Windows更新修复指南:5分钟解决系统更新故障的完整方案
  • 告别‘BCD找不到’:深入理解UEFI时代Windows引导文件藏在哪里(GPT磁盘篇)
  • 告别繁琐存档修改:一站式网页版暗黑破坏神2存档编辑器
  • 李雅普诺夫吸引子驱动AI训练新范式
  • 2026年3月回门宴场地推荐,一站式婚礼/订婚宴/宝宝宴/户外花园婚礼/婚宴/生日宴/公司年会,回门宴门店找哪家 - 品牌推荐师
  • Visual Syslog Server终极指南:Windows系统日志集中监控免费方案
  • 从零开始:PCL启动器终极指南,轻松管理你的Minecraft世界
  • 解决:wsl: 检测到 localhost 代理配置,但未镜像到 WSL。NAT 模式下的 WSL 不支持 localhost 代理
  • 2026 年 DeepSeek 融资与 V4 发布:国产 AI 算力自主挑战与机遇并存
  • Llama-3.2V-11B-cot详细步骤:模型路径配置与自动加载机制解析
  • WinRAR CVE-2023-38831漏洞深度剖析:不只是双击压缩包那么简单
  • JVM调优实战:从垃圾回收到内存模型,一次性搞定JVM核心知识点
  • 51单片机实战:从直流电机调速到步进电机精确定位