高并发下线程打满本质是线程被卡住或无效堆积,需先通过ps和/proc/sys/kernel/threads-max确认是否真逼近系统上限,再用jstack分析runnable、waiting/timed_waiting、blocked三类状态定位阻塞点,结合连接池、外部依赖及netstat排查下游拖慢问题,最后通过限流、熔断、异步隔离和分片执行收敛源头。

高并发下线程打满不是线程数不够,而是线程被卡住或无效堆积。核心思路是:快速识别“活线程”与“死线程”,定位阻塞点或空转逻辑,再分层收口。
先确认是不是真打满
别只看线程总数。执行:
ps -eLf | wc -l 查总线程数
cat /proc/sys/kernel/threads-max 查系统上限
如果两者接近(比如 98%+),才说明逼近瓶颈;若远低于上限但服务已卡,大概率是线程在 WAITING/BLOCKED 状态堆积,而非数量不足。
聚焦 Java 应用的线程状态
对 Java 进程执行:
jstack -l
重点筛三类线程:
- RUNNABLE:真正在 CPU 上跑,可能含死循环、密集计算、空轮询(如 NIO selector.select() 无超时)
- WAITING / TIMED_WAITING:多数卡在锁、连接池获取、远程调用未设超时、sleep 时间过长等
- BLOCKED:明显存在锁竞争,比如多个线程争抢同一把 synchronized 锁或 ReentrantLock
查连接池和外部依赖是否拖住线程
线程打满常因下游“不响应”导致上游线程挂起:
- 数据库连接池活跃数长期等于 maxActive → 检查慢 SQL、连接泄漏、事务未提交
- Redis 客户端线程卡在 jedis.connect() 或 lettuce 的 CommandHandler → 查网络延迟、连接超时、重试配置
- HTTP 调用卡在 HttpClient.execute() → 必须设 connectTimeout 和 socketTimeout,禁用无限重试
用 netstat -anp | grep
收敛源头:限流 + 异步 + 熔断
单靠扩容线程池治标不治本,需加防护层:
- 接入层(Nginx)设 limit_req 控制每秒请求数
- 应用内用 Sentinel 或 Resilience4j 做接口级熔断,失败率超 50% 自动降级
- 非关键路径(如日志上报、埋点、通知)全部异步化,用独立线程池隔离,避免污染主流程
- 批量任务加分布式锁 + 分片执行,禁止单次拉取 10 万条数据在内存里遍历











