本文目录导读:

我来详细解释如何使用jstack检测Java死锁和线程阻塞问题。
死锁示例代码
public class DeadlockDemo {
private static final Object resource1 = new Object();
private static final Object resource2 = new Object();
public static void main(String[] args) {
// 线程1:先锁resource1,再锁resource2
Thread thread1 = new Thread(() -> {
synchronized (resource1) {
System.out.println("Thread 1: locked resource1");
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
synchronized (resource2) {
System.out.println("Thread 1: locked resource2");
}
}
});
// 线程2:先锁resource2,再锁resource1
Thread thread2 = new Thread(() -> {
synchronized (resource2) {
System.out.println("Thread 2: locked resource2");
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
synchronized (resource1) {
System.out.println("Thread 2: locked resource1");
}
}
});
thread1.start();
thread2.start();
}
}
获取jstack信息
方法1:使用jstack命令
# 先找到Java进程ID jps -l # 输出线程堆栈 jstack -l <PID> # 或输出到文件分析 jstack -l <PID> > thread_dump.txt
方法2:使用jcmd命令
jcmd <PID> Thread.print
方法3:使用kill -3(Linux)
kill -3 <PID> # 堆栈信息会输出到标准输出
jstack输出分析
死锁时jstack会明确输出死锁信息:
死锁检测输出示例:
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x00007f8b7c006800 (object 0x000000076b5f6a70, a java.lang.Object),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x00007f8b7c006a00 (object 0x000000076b5f6a80, a java.lang.Object),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at DeadlockDemo.lambda$main$1(DeadlockDemo.java:25)
- waiting to lock <0x000000076b5f6a70> (a java.lang.Object)
- locked <0x000000076b5f6a80> (a java.lang.Object)
"Thread-0":
at DeadlockDemo.lambda$main$0(DeadlockDemo.java:14)
- waiting to lock <0x000000076b5f6a80> (a java.lang.Object)
- locked <0x000000076b5f6a70> (a java.lang.Object)
线程状态分析:
"Thread-0" #12 prio=5 os_prio=0 tid=0x00007f8b7c006800 nid=0x1234 waiting for monitor entry
java.lang.Thread.State: BLOCKED (on object monitor)
阻塞线程检测
阻塞状态的几种类型:
public class BlockingDemo {
private static final Object lock = new Object();
public static void main(String[] args) {
// 线程1:持有锁并长时间等待
Thread thread1 = new Thread(() -> {
synchronized (lock) {
System.out.println("Thread 1: holding lock");
try {
Thread.sleep(10000); // 模拟长时间持有锁
} catch (InterruptedException e) {}
}
});
// 线程2:等待获取锁(BLOCKED状态)
Thread thread2 = new Thread(() -> {
synchronized (lock) {
System.out.println("Thread 2: acquired lock");
}
});
thread1.start();
thread2.start();
}
}
jstack显示的阻塞状态:
"Thread-2" #14 prio=5 os_prio=0 tid=0x00007f8b7c007000 nid=0x1235 waiting for monitor entry
java.lang.Thread.State: BLOCKED (on object monitor)
at BlockingDemo.lambda$main$1(BlockingDemo.java:13)
- waiting to lock <0x000000076b5f6a90> (a java.lang.Object)
- locked <0x000000076b5f6a90> (a java.lang.Object)
常见线程状态及含义
| 状态 | 含义 | jstack显示 |
|---|---|---|
| RUNNABLE | 正在运行 | java.lang.Thread.State: RUNNABLE |
| BLOCKED | 等待锁 | java.lang.Thread.State: BLOCKED (on object monitor) |
| WAITING | 等待通知 | java.lang.Thread.State: WAITING (on object monitor) |
| TIMED_WAITING | 超时等待 | java.lang.Thread.State: TIMED_WAITING (sleeping) |
自动化检测脚本
#!/bin/bash
# detect_deadlock.sh
# 查找Java进程
JAVA_PID=$(jps -l | grep DeadlockDemo | awk '{print $1}')
if [ -z "$JAVA_PID" ]; then
echo "Java process not found"
exit 1
fi
# 获取jstack并检测死锁
jstack -l $JAVA_PID > /tmp/jstack_${JAVA_PID}.txt
# 检测死锁
if grep -q "Found one Java-level deadlock" /tmp/jstack_${JAVA_PID}.txt; then
echo "=== DEADLOCK DETECTED ==="
# 提取死锁详细信息
awk '/Found one Java-level deadlock/,/^$/' /tmp/jstack_${JAVA_PID}.txt
# 发送告警
echo "Send alert: Deadlock detected in process $JAVA_PID"
fi
# 统计阻塞线程数
BLOCKED_COUNT=$(grep -c "BLOCKED" /tmp/jstack_${JAVA_PID}.txt)
echo "Blocked threads count: $BLOCKED_COUNT"
# 输出所有阻塞线程
grep -B 5 "BLOCKED" /tmp/jstack_${JAVA_PID}.txt
实用工具推荐
使用VisualVM(可视化工具)
# 启动VisualVM jvisualvm
使用fastthread.io(在线分析)
- 上传jstack文件到 https://fastthread.io/
- 自动分析死锁和线程问题
使用Thread Dump Analyzer
# 下载并运行 java -jar tda.jar
预防和解决建议
代码层面预防:
public class SafeLockDemo {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public void safeMethod() {
// 保持一致的锁顺序
synchronized (lock1) {
synchronized (lock2) {
// 业务逻辑
}
}
}
// 使用tryLock避免死锁
public void tryLockMethod() {
Lock lock = new ReentrantLock();
try {
if (lock.tryLock(1, TimeUnit.SECONDS)) {
try {
// 业务逻辑
} finally {
lock.unlock();
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
监控建议:
- 定期采集jstack:每30秒采集一次
- 设置告警阈值:阻塞线程数超过阈值时告警
- 自动恢复:检测到死锁时自动重启应用
通过以上方法,可以有效地检测和分析Java死锁及线程阻塞问题。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播