在 Linux 上运行 Java 程序时,线程阻塞是非常常见的一种现象,并不一定代表程序“卡死”。下面从概念 → 常见原因 → Linux 特有点 → 排查方法逐步说明。
线程阻塞(Blocked / Waiting / Timed Waiting)指:
线程暂时无法继续执行,等待某个条件满足(锁、IO、资源、信号等)
在 JVM 中线程状态包括:
RUNNABLE(运行中或可运行)BLOCKED(等 synchronized 锁)WAITING(无限等待,如 wait()、join())TIMED_WAITING(超时等待,如 sleep()、wait(timeout))synchronized(obj) {
// 长时间操作
}
BLOCKEDsocket.getInputStream().read();
Thread.sleep()Object.wait()CountDownLatch.await()BlockingQueue.take()Linux 对每个进程有 FD 限制:
ulimit -n
当:
会导致:
accept() 阻塞Linux 限制:
现象:
pthread_create 失败查看:
cat /proc/sys/kernel/threads-max
Linux 默认是阻塞 IO
会导致 Java 线程直接卡在 write()
TIME_WAIT 过多Java 线程会卡在:
connect()read()现象:
jstack <pid>
重点看:
"BLOCKED"
"waiting to lock"
"RUNNABLE (parking)"
"socketRead0"
top -H -p <pid>
ls /proc/<pid>/fd | wc -l
netstat -anp | grep java
ss -tan | grep ESTAB
| 场景 | 表现 |
|---|---|
| synchronized 死锁 | BLOCKED |
| 网络卡 | RUNNABLE + socketRead |
| 磁盘慢 | RUNNABLE + write |
| 线程过多 | 创建线程卡住 |
| GC | 全部线程暂停 |
Linux 上 Java 线程阻塞,本质上是“等锁、等 IO、等资源、等系统”,Linux 只是把这些限制(FD、线程、IO)暴露得更直接。
如果你有:
jstack 片段我可以帮你精准定位是哪一类阻塞。