Java 并发工具怎么排障:ThreadLocal、AQS 和限流边界

1次阅读
没有评论

Java 并发工具很多,ThreadLocal、AQS、锁、信号量、限流器、异步 I/O 都能解决问题,也都可能制造新问题。使用它们时,最重要的是先分清隔离、同步、限流和异步分别解决什么。

ThreadLocal 是线程隔离,不是自动清理

ThreadLocal 给每个线程一份独立变量,常用于请求上下文、用户信息、traceId、格式化对象等。

它的风险在线程池场景里最明显。线程不会随请求结束而销毁,如果请求结束后没有调用 remove(),旧值会留在线程的 ThreadLocalMap 里,后续请求复用同一线程时可能读到脏数据,也可能造成内存泄漏。

使用建议很简单:谁设置,谁清理。最稳妥的写法是在 try finallyremove()

AQS 是很多同步器的底座

AQS 维护一个 state 和一个等待队列,很多并发工具都基于它实现,例如 ReentrantLockSemaphoreCountDownLatch

独占模式适合一次只允许一个线程执行,例如可重入锁;共享模式适合多个线程同时通过,例如信号量和倒计时门闩。

理解 AQS 的价值不在于每次都去实现同步器,而是在排查锁等待时知道:线程获取资源失败后会进入队列,释放资源时再唤醒后续线程。阻塞不是凭空发生的,它有队列、有状态、有唤醒路径。

限流和并发控制不是一回事

RateLimiter 控制单位时间内允许通过多少请求,关注的是速率。例如每秒 100 个请求。

Semaphore 控制同一时刻最多有多少任务在执行,关注的是并发度。例如最多 4 个上传任务同时跑。

两者经常被混用。抢购接口可能需要限流,避免瞬间请求打满系统;文件上传或批处理更可能需要并发度控制,避免同时占用太多 CPU、内存或连接。

先问清楚要限制的是“每秒多少次”,还是“同时多少个”。

异步 I/O 不是没有成本

异步 I/O 让调用方发起操作后不必一直阻塞等待,CPU 可以继续做别的事。数据会进入内核缓冲区,由操作系统和设备继续处理,完成后再通知应用。

它适合大量 I/O 等待场景,但不意味着业务复杂度消失。异步代码要处理回调、超时、取消、资源释放和错误传播。排障时也要能串起异步链路,否则问题会比同步代码更难定位。

进程和线程排障要看真实状态

线上看到同一个进程下有多个线程、不同状态和不同等待点,不要只看进程名。要结合 PID、线程 ID、状态、CPU 使用、堆栈和父子关系判断。

常见步骤是:

  • 先用 topps 或监控定位高 CPU 或阻塞线程。
  • 再用 jstack、线程 dump 或 profiler 看线程栈。
  • 对线程池问题,结合队列长度、活跃线程数、拒绝次数和任务耗时。

并发排障不能只看一行日志,要把线程状态和业务调用链对上。

实用结论

Java 并发工具要按问题类型选:线程隔离用 ThreadLocal,互斥用锁,资源并发度用 Semaphore,调用速率用 RateLimiter,等待多个任务用 CountDownLatch 或类似工具。

工具本身不难,难的是生命周期和边界。是否清理、是否释放、是否超时、是否可取消、是否能观测,决定了并发代码能不能长期稳定运行。

正文完
 0
bdspAdmin
版权声明:本站原创文章,由 bdspAdmin 于2026-07-05发表,共计1252字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)