第3章:线程分析与死锁检测
1.1.2 线程状态详解NEW(新建):RUNNABLE(可运行):BLOCKED(阻塞):WAITING(等待):TIMED_WAITING(定时等待):TERMINATED(终止):1.2 线程监控指标1.2.1 关键指标2. VisualVM 线程视图2.1 Threads 标签页界面2.2 线程时间线分析2.2.1 颜色编码含义状态颜色映射:2.3 线程详细信息分析2.3.1 线程属性解读
·
1. 线程基础知识
1.1 Java 线程状态
1.1.1 线程生命周期
线程状态转换图:
NEW
│
│ start()
▼
RUNNABLE ◄──────────────────────────────────────┐
│ │
│ 等待锁/IO/sleep() │ notify()/
▼ │ notifyAll()
BLOCKED ──────► WAITING ──────► TIMED_WAITING ───┤
│ │ │ │
│ │ wait() │ sleep() │
│ │ join() │ wait(time) │
│ │ park() │ join(time) │
│ │ │ parkUntil()│
│ │ │ │
│ ▼ ▼ │
└──────────► TERMINATED ◄──────────────────────┘
│
│ 线程结束
▼
[END]
1.1.2 线程状态详解
NEW(新建):
// 线程已创建但尚未启动
Thread thread = new Thread(() -> {
System.out.println("Hello World");
});
// 此时线程状态为 NEW
System.out.println(thread.getState()); // NEW
RUNNABLE(可运行):
// 线程正在运行或准备运行
thread.start();
// 此时线程状态为 RUNNABLE
System.out.println(thread.getState()); // RUNNABLE
BLOCKED(阻塞):
// 线程等待获取同步锁
public class BlockedExample {
private static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
synchronized (lock) {
try {
Thread.sleep(10000); // 持有锁10秒
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
Thread t2 = new Thread(() -> {
synchronized (lock) { // 等待获取锁,状态为 BLOCKED
System.out.println("Got the lock");
}
});
t1.start();
Thread.sleep(100); // 确保 t1 先获取锁
t2.start();
Thread.sleep(100);
System.out.println("t2 state: " + t2.getState()); // BLOCKED
}
}
WAITING(等待):
// 线程无限期等待另一个线程的特定操作
public class WaitingExample {
private static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Thread waiter = new Thread(() -> {
synchronized (lock) {
try {
lock.wait(); // 状态变为 WAITING
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
waiter.start();
Thread.sleep(100);
System.out.println("waiter state: " + waiter.getState()); // WAITING
// 唤醒等待的线程
synchronized (lock) {
lock.notify();
}
}
}
TIMED_WAITING(定时等待):
// 线程等待指定的时间
public class TimedWaitingExample {
public static void main(String[] args) throws InterruptedException {
Thread sleeper = new Thread(() -> {
try {
Thread.sleep(5000); // 状态为 TIMED_WAITING
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
sleeper.start();
Thread.sleep(100);
System.out.println("sleeper state: " + sleeper.getState()); // TIMED_WAITING
}
}
TERMINATED(终止):
// 线程已完成执行
Thread finishedThread = new Thread(() -> {
System.out.println("Task completed");
});
finishedThread.start();
finishedThread.join(); // 等待线程完成
System.out.println("finished state: " + finishedThread.getState()); // TERMINATED
1.2 线程监控指标
1.2.1 关键指标
// 线程监控指标收集器
import java.lang.management.*;
import java.util.*;
public class ThreadMetricsCollector {
private static final ThreadMXBean threadBean =
ManagementFactory.getThreadMXBean();
public static class ThreadMetrics {
public final int liveThreads;
public final int peakThreads;
public final int daemonThreads;
public final long totalStartedThreads;
public final Map<Thread.State, Integer> threadsByState;
public final List<ThreadInfo> deadlockedThreads;
public ThreadMetrics() {
this.liveThreads = threadBean.getThreadCount();
this.peakThreads = threadBean.getPeakThreadCount();
this.daemonThreads = threadBean.getDaemonThreadCount();
this.totalStartedThreads = threadBean.getTotalStartedThreadCount();
this.threadsByState = getThreadsByState();
this.deadlockedThreads = getDeadlockedThreads();
}
private Map<Thread.State, Integer> getThreadsByState() {
Map<Thread.State, Integer> stateCount = new EnumMap<>(Thread.State.class);
// 初始化所有状态计数为0
for (Thread.State state : Thread.State.values()) {
stateCount.put(state, 0);
}
// 统计各状态线程数量
long[] threadIds = threadBean.getAllThreadIds();
ThreadInfo[] threadInfos = threadBean.getThreadInfo(threadIds);
for (ThreadInfo info : threadInfos) {
if (info != null) {
Thread.State state = info.getThreadState();
stateCount.put(state, stateCount.get(state) + 1);
}
}
return stateCount;
}
private List<ThreadInfo> getDeadlockedThreads() {
List<ThreadInfo> deadlocked = new ArrayList<>();
// 检查死锁
long[] deadlockedThreadIds = threadBean.findDeadlockedThreads();
if (deadlockedThreadIds != null) {
ThreadInfo[] threadInfos = threadBean.getThreadInfo(deadlockedThreadIds);
deadlocked.addAll(Arrays.asList(threadInfos));
}
return deadlocked;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("=== Thread Metrics ===\n");
sb.append(String.format("Live Threads: %d\n", liveThreads));
sb.append(String.format("Peak Threads: %d\n", peakThreads));
sb.append(String.format("Daemon Threads: %d\n", daemonThreads));
sb.append(String.format("Total Started: %d\n", totalStartedThreads));
sb.append("\nThreads by State:\n");
for (Map.Entry<Thread.State, Integer> entry : threadsByState.entrySet()) {
if (entry.getValue() > 0) {
sb.append(String.format(" %s: %d\n", entry.getKey(), entry.getValue()));
}
}
if (!deadlockedThreads.isEmpty()) {
sb.append(String.format("\nDEADLOCK DETECTED! %d threads involved\n",
deadlockedThreads.size()));
}
return sb.toString();
}
}
public static ThreadMetrics collect() {
return new ThreadMetrics();
}
public static void main(String[] args) throws InterruptedException {
// 创建一些测试线程
createTestThreads();
// 定期收集指标
for (int i = 0; i < 10; i++) {
ThreadMetrics metrics = collect();
System.out.println(metrics);
System.out.println("=".repeat(50));
Thread.sleep(5000);
}
}
private static void createTestThreads() {
// 创建一些不同状态的线程用于测试
// RUNNABLE 线程
new Thread(() -> {
while (true) {
// 忙等待
Math.random();
}
}, "BusyThread").start();
// TIMED_WAITING 线程
new Thread(() -> {
while (true) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "SleepingThread").start();
// WAITING 线程
Object waitLock = new Object();
new Thread(() -> {
synchronized (waitLock) {
try {
waitLock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "WaitingThread").start();
}
}
2. VisualVM 线程视图
2.1 Threads 标签页界面
┌─────────────────────────────────────────────────────────────┐
│ Threads │
├─────────────────────────────────────────────────────────────┤
│ 线程时间线图表 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Thread Timeline │ │
│ │ │ │
│ │ main ████████████████████████████████████████ │ │
│ │ Thread-1 ████████████████████████████████████████ │ │
│ │ Thread-2 ████████████████████████████████████████ │ │
│ │ GC Thread ████████████████████████████████████████ │ │
│ │ Finalizer ████████████████████████████████████████ │ │
│ │ │ │
│ │ 绿色: RUNNABLE 黄色: BLOCKED 红色: WAITING │ │
│ │ 蓝色: TIMED_WAITING 灰色: TERMINATED │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ 线程详细信息 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Name: main State: RUNNABLE │ │
│ │ Priority: 5 Daemon: false │ │
│ │ Thread ID: 1 Native ID: 12345 │ │
│ │ │ │
│ │ Stack Trace: │ │
│ │ java.lang.Thread.sleep(Native Method) │ │
│ │ com.example.Main.main(Main.java:25) │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
2.2 线程时间线分析
2.2.1 颜色编码含义
状态颜色映射:
- 绿色 (RUNNABLE):线程正在运行或可以运行
- 黄色 (BLOCKED):线程被阻塞,等待获取同步锁
- 红色 (WAITING):线程无限期等待
- 蓝色 (TIMED_WAITING):线程定时等待
- 灰色 (TERMINATED):线程已终止
2.2.2 时间线模式分析
// 创建不同模式的线程用于观察
public class ThreadPatternDemo {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public static void main(String[] args) {
// 模式1:CPU密集型线程(持续绿色)
createCpuIntensiveThread();
// 模式2:IO密集型线程(绿色和蓝色交替)
createIoIntensiveThread();
// 模式3:锁竞争线程(绿色和黄色交替)
createLockContentionThreads();
// 模式4:生产者-消费者线程(多种颜色交替)
createProducerConsumerThreads();
// 保持主线程运行
try {
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
// CPU密集型线程 - 持续RUNNABLE状态
private static void createCpuIntensiveThread() {
Thread cpuThread = new Thread(() -> {
while (true) {
// 执行计算密集型任务
double result = 0;
for (int i = 0; i < 1000000; i++) {
result += Math.sqrt(i) * Math.sin(i);
}
// 偶尔让出CPU
if (Math.random() < 0.001) {
Thread.yield();
}
}
}, "CPU-Intensive-Thread");
cpuThread.start();
}
// IO密集型线程 - RUNNABLE和TIMED_WAITING交替
private static void createIoIntensiveThread() {
Thread ioThread = new Thread(() -> {
while (true) {
try {
// 模拟IO操作
System.out.println("Performing IO operation...");
// 模拟IO等待
Thread.sleep(100 + (int)(Math.random() * 200));
// 模拟处理数据
for (int i = 0; i < 10000; i++) {
Math.random();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "IO-Intensive-Thread");
ioThread.start();
}
// 锁竞争线程 - RUNNABLE和BLOCKED交替
private static void createLockContentionThreads() {
for (int i = 0; i < 3; i++) {
final int threadId = i;
Thread lockThread = new Thread(() -> {
while (true) {
synchronized (lock1) {
try {
// 持有锁一段时间
Thread.sleep(50 + (int)(Math.random() * 100));
// 执行一些工作
for (int j = 0; j < 10000; j++) {
Math.random();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
// 释放锁后稍作休息
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "Lock-Contention-Thread-" + threadId);
lockThread.start();
}
}
// 生产者-消费者线程 - 多种状态交替
private static void createProducerConsumerThreads() {
java.util.concurrent.BlockingQueue<String> queue =
new java.util.concurrent.ArrayBlockingQueue<>(10);
// 生产者线程
Thread producer = new Thread(() -> {
int count = 0;
while (true) {
try {
String item = "Item-" + (++count);
queue.put(item); // 可能会WAITING如果队列满了
System.out.println("Produced: " + item);
// 生产间隔
Thread.sleep(50 + (int)(Math.random() * 100));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "Producer-Thread");
// 消费者线程
Thread consumer = new Thread(() -> {
while (true) {
try {
String item = queue.take(); // 可能会WAITING如果队列空了
System.out.println("Consumed: " + item);
// 处理时间
Thread.sleep(100 + (int)(Math.random() * 200));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "Consumer-Thread");
producer.start();
consumer.start();
}
}
2.3 线程详细信息分析
2.3.1 线程属性解读
// 线程信息分析器
import java.lang.management.*;
public class ThreadInfoAnalyzer {
private static final ThreadMXBean threadBean =
ManagementFactory.getThreadMXBean();
public static void analyzeThread(long threadId) {
ThreadInfo threadInfo = threadBean.getThreadInfo(threadId, Integer.MAX_VALUE);
if (threadInfo == null) {
System.out.println("Thread not found: " + threadId);
return;
}
System.out.println("=== Thread Analysis ===");
System.out.println("Thread ID: " + threadInfo.getThreadId());
System.out.println("Thread Name: " + threadInfo.getThreadName());
System.out.println("Thread State: " + threadInfo.getThreadState());
// 阻塞信息
System.out.println("Blocked Count: " + threadInfo.getBlockedCount());
System.out.println("Blocked Time: " + threadInfo.getBlockedTime() + "ms");
// 等待信息
System.out.println("Waited Count: " + threadInfo.getWaitedCount());
System.out.println("Waited Time: " + threadInfo.getWaitedTime() + "ms");
// 锁信息
if (threadInfo.getLockName() != null) {
System.out.println("Lock Name: " + threadInfo.getLockName());
System.out.println("Lock Owner: " + threadInfo.getLockOwnerName());
System.out.println("Lock Owner ID: " + threadInfo.getLockOwnerId());
}
// 栈跟踪
System.out.println("\nStack Trace:");
StackTraceElement[] stackTrace = threadInfo.getStackTrace();
for (int i = 0; i < Math.min(stackTrace.length, 10); i++) {
System.out.println(" " + stackTrace[i]);
}
if (stackTrace.length > 10) {
System.out.println(" ... (" + (stackTrace.length - 10) + " more frames)");
}
// 锁信息详细分析
MonitorInfo[] monitors = threadInfo.getLockedMonitors();
if (monitors.length > 0) {
System.out.println("\nLocked Monitors:");
for (MonitorInfo monitor : monitors) {
System.out.println(" " + monitor.getClassName() + "@" +
Integer.toHexString(monitor.getIdentityHashCode()));
System.out.println(" at " + monitor.getLockedStackFrame());
}
}
LockInfo[] locks = threadInfo.getLockedSynchronizers();
if (locks.length > 0) {
System.out.println("\nLocked Synchronizers:");
for (LockInfo lock : locks) {
System.out.println(" " + lock.getClassName() + "@" +
Integer.toHexString(lock.getIdentityHashCode()));
}
}
}
public static void analyzeAllThreads() {
long[] threadIds = threadBean.getAllThreadIds();
System.out.println("=== All Threads Analysis ===");
System.out.println("Total threads: " + threadIds.length);
System.out.println();
for (long threadId : threadIds) {
analyzeThread(threadId);
System.out.println("\n" + "=".repeat(50) + "\n");
}
}
public static void main(String[] args) {
// 分析所有线程
analyzeAllThreads();
}
}
2.3.2 栈跟踪分析
// 栈跟踪分析工具
public class StackTraceAnalyzer {
public static class StackAnalysisResult {
public final String threadName;
public final Thread.State state;
public final String topMethod;
public final String blockingResource;
public final int stackDepth;
public final boolean isInNativeMethod;
public final boolean isInSystemCode;
public StackAnalysisResult(ThreadInfo threadInfo) {
this.threadName = threadInfo.getThreadName();
this.state = threadInfo.getThreadState();
StackTraceElement[] stack = threadInfo.getStackTrace();
this.stackDepth = stack.length;
if (stack.length > 0) {
StackTraceElement top = stack[0];
this.topMethod = top.getClassName() + "." + top.getMethodName();
this.isInNativeMethod = top.isNativeMethod();
this.isInSystemCode = isSystemCode(top.getClassName());
} else {
this.topMethod = "<empty stack>";
this.isInNativeMethod = false;
this.isInSystemCode = false;
}
this.blockingResource = threadInfo.getLockName();
}
private boolean isSystemCode(String className) {
return className.startsWith("java.") ||
className.startsWith("javax.") ||
className.startsWith("sun.") ||
className.startsWith("com.sun.");
}
public String getAnalysis() {
StringBuilder analysis = new StringBuilder();
analysis.append(String.format("Thread: %s [%s]\n", threadName, state));
analysis.append(String.format("Top Method: %s\n", topMethod));
analysis.append(String.format("Stack Depth: %d\n", stackDepth));
if (isInNativeMethod) {
analysis.append("⚠️ Currently in native method\n");
}
if (isInSystemCode) {
analysis.append("ℹ️ Currently in system code\n");
}
if (blockingResource != null) {
analysis.append(String.format("🔒 Blocked on: %s\n", blockingResource));
}
// 状态特定分析
switch (state) {
case BLOCKED:
analysis.append("🚫 Thread is blocked waiting for a lock\n");
break;
case WAITING:
analysis.append("⏳ Thread is waiting indefinitely\n");
break;
case TIMED_WAITING:
analysis.append("⏰ Thread is waiting for a specified time\n");
break;
case RUNNABLE:
if (isInNativeMethod) {
analysis.append("🔧 Thread may be doing I/O or native operations\n");
} else {
analysis.append("✅ Thread is actively running\n");
}
break;
}
return analysis.toString();
}
}
public static void analyzeAllThreadStacks() {
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
long[] threadIds = threadBean.getAllThreadIds();
ThreadInfo[] threadInfos = threadBean.getThreadInfo(threadIds, Integer.MAX_VALUE);
System.out.println("=== Stack Trace Analysis ===");
for (ThreadInfo threadInfo : threadInfos) {
if (threadInfo != null) {
StackAnalysisResult result = new StackAnalysisResult(threadInfo);
System.out.println(result.getAnalysis());
System.out.println("-".repeat(40));
}
}
}
public static void main(String[] args) {
// 创建一些测试线程
createTestScenarios();
// 等待线程启动
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 分析栈跟踪
analyzeAllThreadStacks();
}
private static void createTestScenarios() {
// 场景1:IO等待
new Thread(() -> {
try {
java.net.ServerSocket server = new java.net.ServerSocket(0);
server.accept(); // 阻塞在IO操作
} catch (Exception e) {
// 忽略异常
}
}, "IO-Waiting-Thread").start();
// 场景2:锁等待
Object lock = new Object();
new Thread(() -> {
synchronized (lock) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "Lock-Holder-Thread").start();
new Thread(() -> {
synchronized (lock) {
System.out.println("Got lock");
}
}, "Lock-Waiter-Thread").start();
// 场景3:计算密集型
new Thread(() -> {
while (true) {
Math.sqrt(Math.random());
}
}, "CPU-Intensive-Thread").start();
}
}
3. 死锁检测
3.1 死锁基础理论
3.1.1 死锁的四个必要条件
- 互斥条件:资源不能被多个线程同时使用
- 持有和等待条件:线程持有资源的同时等待其他资源
- 不可剥夺条件:资源不能被强制从线程中剥夺
- 循环等待条件:存在线程资源的循环等待链
3.1.2 常见死锁模式
经典死锁示例:
// 经典的两个锁死锁
public class ClassicDeadlock {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (lock1) {
System.out.println("Thread 1: Holding lock 1...");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
}, "DeadLock-Thread-1");
Thread thread2 = new Thread(() -> {
synchronized (lock2) {
System.out.println("Thread 2: Holding lock 2...");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (lock1) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}, "DeadLock-Thread-2");
thread1.start();
thread2.start();
// 等待死锁发生
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 检测死锁
detectDeadlock();
}
private static void detectDeadlock() {
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
long[] deadlockedThreads = threadBean.findDeadlockedThreads();
if (deadlockedThreads != null) {
System.out.println("\n🚨 DEADLOCK DETECTED! 🚨");
System.out.println("Deadlocked threads: " + deadlockedThreads.length);
ThreadInfo[] threadInfos = threadBean.getThreadInfo(deadlockedThreads);
for (ThreadInfo threadInfo : threadInfos) {
System.out.println("\nThread: " + threadInfo.getThreadName());
System.out.println("State: " + threadInfo.getThreadState());
System.out.println("Blocked on: " + threadInfo.getLockName());
System.out.println("Blocked by: " + threadInfo.getLockOwnerName());
}
} else {
System.out.println("No deadlock detected.");
}
}
}
复杂死锁示例:
// 多线程多锁死锁
public class ComplexDeadlock {
private static final Object lockA = new Object();
private static final Object lockB = new Object();
private static final Object lockC = new Object();
public static void main(String[] args) {
// 创建循环等待:Thread1 → A → B, Thread2 → B → C, Thread3 → C → A
Thread thread1 = new Thread(() -> {
synchronized (lockA) {
System.out.println("Thread 1: Got lock A");
sleep(100);
synchronized (lockB) {
System.out.println("Thread 1: Got lock B");
}
}
}, "Complex-DeadLock-Thread-1");
Thread thread2 = new Thread(() -> {
synchronized (lockB) {
System.out.println("Thread 2: Got lock B");
sleep(100);
synchronized (lockC) {
System.out.println("Thread 2: Got lock C");
}
}
}, "Complex-DeadLock-Thread-2");
Thread thread3 = new Thread(() -> {
synchronized (lockC) {
System.out.println("Thread 3: Got lock C");
sleep(100);
synchronized (lockA) {
System.out.println("Thread 3: Got lock A");
}
}
}, "Complex-DeadLock-Thread-3");
thread1.start();
thread2.start();
thread3.start();
// 等待死锁发生并检测
sleep(1000);
new DeadlockDetector().detectAndAnalyze();
}
private static void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
3.2 VisualVM 死锁检测
3.2.1 死锁检测界面
在 VisualVM 的 Threads 标签页中,当检测到死锁时会显示:
┌─────────────────────────────────────────────────────────────┐
│ 🚨 DEADLOCK DETECTED 🚨 │
├─────────────────────────────────────────────────────────────┤
│ 死锁线程列表: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Thread Name State Blocked On │ │
│ │ DeadLock-Thread-1 BLOCKED java.lang.Object@abc123 │ │
│ │ DeadLock-Thread-2 BLOCKED java.lang.Object@def456 │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ 死锁循环链: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ DeadLock-Thread-1 → Object@abc123 → DeadLock-Thread-2 │ │
│ │ DeadLock-Thread-2 → Object@def456 → DeadLock-Thread-1 │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
3.2.2 死锁分析工具
// 高级死锁检测和分析工具
import java.lang.management.*;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class DeadlockDetector {
private static final ThreadMXBean threadBean =
ManagementFactory.getThreadMXBean();
private final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
public static class DeadlockInfo {
public final long[] deadlockedThreadIds;
public final ThreadInfo[] deadlockedThreadInfos;
public final Map<Long, String> threadNames;
public final Map<Long, String> lockChain;
public final long detectionTime;
public DeadlockInfo(long[] threadIds, ThreadInfo[] threadInfos) {
this.deadlockedThreadIds = threadIds;
this.deadlockedThreadInfos = threadInfos;
this.detectionTime = System.currentTimeMillis();
this.threadNames = new HashMap<>();
this.lockChain = new HashMap<>();
// 构建线程名映射和锁链
for (ThreadInfo info : threadInfos) {
threadNames.put(info.getThreadId(), info.getThreadName());
if (info.getLockOwnerId() != -1) {
lockChain.put(info.getThreadId(),
threadNames.get(info.getLockOwnerId()));
}
}
}
public void printAnalysis() {
System.out.println("\n🚨 ===== DEADLOCK ANALYSIS ===== 🚨");
System.out.println("Detection Time: " + new Date(detectionTime));
System.out.println("Deadlocked Threads: " + deadlockedThreadIds.length);
System.out.println();
// 打印每个死锁线程的详细信息
for (ThreadInfo info : deadlockedThreadInfos) {
printThreadDeadlockInfo(info);
System.out.println();
}
// 打印死锁循环链
printDeadlockCycle();
// 提供解决建议
printResolutionSuggestions();
}
private void printThreadDeadlockInfo(ThreadInfo info) {
System.out.println("Thread: " + info.getThreadName() +
" (ID: " + info.getThreadId() + ")");
System.out.println("State: " + info.getThreadState());
System.out.println("Blocked on: " + info.getLockName());
System.out.println("Lock owner: " + info.getLockOwnerName() +
" (ID: " + info.getLockOwnerId() + ")");
// 打印关键栈帧
StackTraceElement[] stack = info.getStackTrace();
System.out.println("Key stack frames:");
for (int i = 0; i < Math.min(stack.length, 5); i++) {
StackTraceElement frame = stack[i];
System.out.println(" at " + frame);
// 标记同步块
if (frame.getMethodName().contains("synchronized") ||
(i < stack.length - 1 &&
stack[i + 1].getMethodName().contains("synchronized"))) {
System.out.println(" ^ Synchronization point");
}
}
}
private void printDeadlockCycle() {
System.out.println("🔄 Deadlock Cycle:");
// 构建循环链
Set<Long> visited = new HashSet<>();
for (long threadId : deadlockedThreadIds) {
if (!visited.contains(threadId)) {
List<String> cycle = buildCycle(threadId, visited);
if (cycle.size() > 1) {
System.out.println(" " + String.join(" → ", cycle) +
" → " + cycle.get(0));
}
}
}
}
private List<String> buildCycle(long startThreadId, Set<Long> visited) {
List<String> cycle = new ArrayList<>();
long currentThreadId = startThreadId;
while (!visited.contains(currentThreadId)) {
visited.add(currentThreadId);
String threadName = threadNames.get(currentThreadId);
cycle.add(threadName);
// 找到这个线程等待的锁的拥有者
ThreadInfo info = null;
for (ThreadInfo ti : deadlockedThreadInfos) {
if (ti.getThreadId() == currentThreadId) {
info = ti;
break;
}
}
if (info != null && info.getLockOwnerId() != -1) {
currentThreadId = info.getLockOwnerId();
} else {
break;
}
}
return cycle;
}
private void printResolutionSuggestions() {
System.out.println("💡 Resolution Suggestions:");
System.out.println("1. 🔄 Restart the application to break the deadlock");
System.out.println("2. 📋 Review lock acquisition order in the code");
System.out.println("3. ⏱️ Consider using timeout-based locking");
System.out.println("4. 🔧 Implement lock ordering to prevent future deadlocks");
System.out.println("5. 🧪 Use java.util.concurrent utilities instead of synchronized");
// 分析锁的获取模式
analyzeLockPatterns();
}
private void analyzeLockPatterns() {
System.out.println("\n🔍 Lock Pattern Analysis:");
Map<String, Integer> lockTypes = new HashMap<>();
Map<String, Integer> methodPatterns = new HashMap<>();
for (ThreadInfo info : deadlockedThreadInfos) {
// 分析锁类型
String lockName = info.getLockName();
if (lockName != null) {
String lockType = lockName.substring(0, lockName.indexOf('@'));
lockTypes.put(lockType, lockTypes.getOrDefault(lockType, 0) + 1);
}
// 分析方法模式
StackTraceElement[] stack = info.getStackTrace();
for (StackTraceElement frame : stack) {
String method = frame.getClassName() + "." + frame.getMethodName();
if (!method.startsWith("java.") && !method.startsWith("sun.")) {
methodPatterns.put(method,
methodPatterns.getOrDefault(method, 0) + 1);
break; // 只记录第一个非系统方法
}
}
}
System.out.println("Lock types involved:");
lockTypes.forEach((type, count) ->
System.out.println(" " + type + ": " + count + " threads"));
System.out.println("Methods involved:");
methodPatterns.forEach((method, count) ->
System.out.println(" " + method + ": " + count + " threads"));
}
}
public DeadlockInfo detectDeadlock() {
long[] deadlockedThreads = threadBean.findDeadlockedThreads();
if (deadlockedThreads != null && deadlockedThreads.length > 0) {
ThreadInfo[] threadInfos = threadBean.getThreadInfo(deadlockedThreads);
return new DeadlockInfo(deadlockedThreads, threadInfos);
}
return null;
}
public void detectAndAnalyze() {
DeadlockInfo deadlockInfo = detectDeadlock();
if (deadlockInfo != null) {
deadlockInfo.printAnalysis();
} else {
System.out.println("✅ No deadlock detected.");
}
}
public void startContinuousMonitoring(int intervalSeconds) {
System.out.println("🔍 Starting continuous deadlock monitoring...");
System.out.println("Check interval: " + intervalSeconds + " seconds");
scheduler.scheduleAtFixedRate(() -> {
DeadlockInfo deadlockInfo = detectDeadlock();
if (deadlockInfo != null) {
System.out.println("\n⚠️ DEADLOCK DETECTED AT " + new Date());
deadlockInfo.printAnalysis();
// 可以在这里添加告警逻辑
sendDeadlockAlert(deadlockInfo);
}
}, 0, intervalSeconds, TimeUnit.SECONDS);
}
private void sendDeadlockAlert(DeadlockInfo deadlockInfo) {
// 这里可以实现告警逻辑,比如:
// - 发送邮件
// - 写入日志文件
// - 调用监控系统API
// - 生成堆转储文件
System.out.println("📧 Deadlock alert sent!");
// 示例:生成线程转储文件
generateThreadDump(deadlockInfo);
}
private void generateThreadDump(DeadlockInfo deadlockInfo) {
try {
String timestamp = String.valueOf(System.currentTimeMillis());
String filename = "deadlock_thread_dump_" + timestamp + ".txt";
try (java.io.PrintWriter writer = new java.io.PrintWriter(
new java.io.FileWriter(filename))) {
writer.println("Deadlock Thread Dump");
writer.println("Generated at: " + new Date(deadlockInfo.detectionTime));
writer.println("=".repeat(50));
// 写入所有线程信息
long[] allThreadIds = threadBean.getAllThreadIds();
ThreadInfo[] allThreadInfos = threadBean.getThreadInfo(
allThreadIds, Integer.MAX_VALUE);
for (ThreadInfo info : allThreadInfos) {
if (info != null) {
writer.println("\nThread: " + info.getThreadName());
writer.println("State: " + info.getThreadState());
if (info.getLockName() != null) {
writer.println("Blocked on: " + info.getLockName());
}
writer.println("Stack trace:");
for (StackTraceElement frame : info.getStackTrace()) {
writer.println(" at " + frame);
}
writer.println();
}
}
}
System.out.println("📄 Thread dump saved to: " + filename);
} catch (java.io.IOException e) {
System.err.println("Failed to generate thread dump: " + e.getMessage());
}
}
public void shutdown() {
scheduler.shutdown();
}
public static void main(String[] args) {
DeadlockDetector detector = new DeadlockDetector();
// 立即检测一次
detector.detectAndAnalyze();
// 启动连续监控
detector.startContinuousMonitoring(10);
// 保持程序运行
try {
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
detector.shutdown();
}
}
}
3.3 死锁预防和解决
3.3.1 死锁预防策略
锁排序策略:
// 通过锁排序避免死锁
public class DeadlockPrevention {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
// 为锁分配唯一的ID
private static final int LOCK1_ID = System.identityHashCode(lock1);
private static final int LOCK2_ID = System.identityHashCode(lock2);
// 安全的双锁方法
public static void safeDoublelock(Runnable task) {
Object firstLock, secondLock;
// 总是按照相同的顺序获取锁
if (LOCK1_ID < LOCK2_ID) {
firstLock = lock1;
secondLock = lock2;
} else {
firstLock = lock2;
secondLock = lock1;
}
synchronized (firstLock) {
synchronized (secondLock) {
task.run();
}
}
}
public static void main(String[] args) {
// 两个线程都使用相同的锁顺序,避免死锁
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 100; i++) {
safeDoublelock(() -> {
System.out.println("Thread 1: iteration " + i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
}, "Safe-Thread-1");
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 100; i++) {
safeDoublelock(() -> {
System.out.println("Thread 2: iteration " + i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
}, "Safe-Thread-2");
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("✅ Completed without deadlock!");
}
}
超时锁策略:
// 使用超时避免死锁
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.TimeUnit;
public class TimeoutLockStrategy {
private static final ReentrantLock lock1 = new ReentrantLock();
private static final ReentrantLock lock2 = new ReentrantLock();
private static final int TIMEOUT_MS = 1000;
public static boolean tryDoublelock(Runnable task) {
boolean lock1Acquired = false;
boolean lock2Acquired = false;
try {
// 尝试获取第一个锁
lock1Acquired = lock1.tryLock(TIMEOUT_MS, TimeUnit.MILLISECONDS);
if (!lock1Acquired) {
System.out.println("Failed to acquire lock1 within timeout");
return false;
}
// 尝试获取第二个锁
lock2Acquired = lock2.tryLock(TIMEOUT_MS, TimeUnit.MILLISECONDS);
if (!lock2Acquired) {
System.out.println("Failed to acquire lock2 within timeout");
return false;
}
// 执行任务
task.run();
return true;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
} finally {
// 释放锁(按相反顺序)
if (lock2Acquired) {
lock2.unlock();
}
if (lock1Acquired) {
lock1.unlock();
}
}
}
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
boolean success = tryDoublelock(() -> {
System.out.println("Thread 1: Got both locks, iteration " + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
if (!success) {
System.out.println("Thread 1: Failed to get locks, retrying...");
try {
Thread.sleep(50); // 短暂等待后重试
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
}, "Timeout-Thread-1");
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
boolean success = tryDoublelock(() -> {
System.out.println("Thread 2: Got both locks, iteration " + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
if (!success) {
System.out.println("Thread 2: Failed to get locks, retrying...");
try {
Thread.sleep(50);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
}, "Timeout-Thread-2");
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("✅ Completed with timeout-based locking!");
}
}
4. 线程转储分析
4.1 生成线程转储
4.1.1 通过 VisualVM 生成
在 VisualVM 中生成线程转储:
- 右键点击应用程序
- 选择 “Thread Dump”
- 线程转储会在新标签页中打开
4.1.2 通过命令行生成
# 使用 jstack 生成线程转储
jstack <PID> > thread_dump.txt
# 使用 kill 信号生成(Linux/macOS)
kill -3 <PID>
# 使用 JVM 参数在 OOM 时自动生成
java -XX:+PrintGCDetails \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:+PrintConcurrentLocks \
YourApplication
4.1.3 程序化生成
// 程序化生成线程转储
import java.lang.management.*;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class ThreadDumpGenerator {
private static final ThreadMXBean threadBean =
ManagementFactory.getThreadMXBean();
public static void generateThreadDump(String filename) {
try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
writer.println("Thread Dump");
writer.println("Generated at: " + LocalDateTime.now());
writer.println("JVM: " + System.getProperty("java.vm.name") +
" " + System.getProperty("java.vm.version"));
writer.println("=".repeat(80));
writer.println();
// 获取所有线程信息
long[] threadIds = threadBean.getAllThreadIds();
ThreadInfo[] threadInfos = threadBean.getThreadInfo(
threadIds, Integer.MAX_VALUE);
// 检查死锁
long[] deadlockedThreads = threadBean.findDeadlockedThreads();
if (deadlockedThreads != null) {
writer.println("🚨 DEADLOCK DETECTED!");
writer.println("Deadlocked threads: " + deadlockedThreads.length);
writer.println();
}
// 写入每个线程的详细信息
for (ThreadInfo threadInfo : threadInfos) {
if (threadInfo != null) {
writeThreadInfo(writer, threadInfo, deadlockedThreads);
writer.println();
}
}
System.out.println("Thread dump generated: " + filename);
} catch (IOException e) {
System.err.println("Failed to generate thread dump: " + e.getMessage());
}
}
private static void writeThreadInfo(PrintWriter writer, ThreadInfo threadInfo,
long[] deadlockedThreads) {
boolean isDeadlocked = deadlockedThreads != null &&
java.util.Arrays.stream(deadlockedThreads)
.anyMatch(id -> id == threadInfo.getThreadId());
writer.println("Thread: " + threadInfo.getThreadName() +
(isDeadlocked ? " [DEADLOCKED]" : ""));
writer.println("ID: " + threadInfo.getThreadId());
writer.println("State: " + threadInfo.getThreadState());
if (threadInfo.getLockName() != null) {
writer.println("Blocked on: " + threadInfo.getLockName());
writer.println("Lock owner: " + threadInfo.getLockOwnerName() +
" (ID: " + threadInfo.getLockOwnerId() + ")");
}
writer.println("Blocked count: " + threadInfo.getBlockedCount());
writer.println("Waited count: " + threadInfo.getWaitedCount());
// 栈跟踪
writer.println("Stack trace:");
StackTraceElement[] stackTrace = threadInfo.getStackTrace();
for (StackTraceElement frame : stackTrace) {
writer.println(" at " + frame);
}
// 锁信息
MonitorInfo[] monitors = threadInfo.getLockedMonitors();
if (monitors.length > 0) {
writer.println("Locked monitors:");
for (MonitorInfo monitor : monitors) {
writer.println(" " + monitor.getClassName() + "@" +
Integer.toHexString(monitor.getIdentityHashCode()));
}
}
LockInfo[] locks = threadInfo.getLockedSynchronizers();
if (locks.length > 0) {
writer.println("Locked synchronizers:");
for (LockInfo lock : locks) {
writer.println(" " + lock.getClassName() + "@" +
Integer.toHexString(lock.getIdentityHashCode()));
}
}
}
public static void main(String[] args) {
String timestamp = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")
.format(LocalDateTime.now());
String filename = "thread_dump_" + timestamp + ".txt";
generateThreadDump(filename);
}
}
4.2 线程转储分析
4.2.1 转储文件结构
典型的线程转储文件结构:
Thread Dump
Generated at: 2024-01-15T10:30:45
JVM: OpenJDK 64-Bit Server VM 11.0.16
================================================================================
🚨 DEADLOCK DETECTED!
Deadlocked threads: 2
Thread: DeadLock-Thread-1 [DEADLOCKED]
ID: 12
State: BLOCKED
Blocked on: java.lang.Object@1a2b3c4d
Lock owner: DeadLock-Thread-2 (ID: 13)
Blocked count: 1
Waited count: 0
Stack trace:
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at com.example.DeadlockExample.method1(DeadlockExample.java:25)
at com.example.DeadlockExample.lambda$main$0(DeadlockExample.java:15)
at java.lang.Thread.run(Thread.java:748)
Thread: DeadLock-Thread-2 [DEADLOCKED]
ID: 13
State: BLOCKED
Blocked on: java.lang.Object@5e6f7a8b
Lock owner: DeadLock-Thread-1 (ID: 12)
Blocked count: 1
Waited count: 0
Stack trace:
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at com.example.DeadlockExample.method2(DeadlockExample.java:35)
at com.example.DeadlockExample.lambda$main$1(DeadlockExample.java:20)
at java.lang.Thread.run(Thread.java:748)
4.2.2 自动化分析工具
// 线程转储自动分析工具
import java.io.*;
import java.util.*;
import java.util.regex.*;
public class ThreadDumpAnalyzer {
public static class AnalysisResult {
public int totalThreads;
public Map<Thread.State, Integer> threadsByState;
public List<String> deadlockedThreads;
public Map<String, Integer> blockedOnResources;
public Map<String, Integer> topStackFrames;
public List<String> suspiciousPatterns;
public Map<String, Integer> threadNamePatterns;
public AnalysisResult() {
threadsByState = new EnumMap<>(Thread.State.class);
deadlockedThreads = new ArrayList<>();
blockedOnResources = new HashMap<>();
topStackFrames = new HashMap<>();
suspiciousPatterns = new ArrayList<>();
threadNamePatterns = new HashMap<>();
}
public void printSummary() {
System.out.println("=== Thread Dump Analysis Summary ===");
System.out.println("Total threads: " + totalThreads);
System.out.println("\nThreads by state:");
threadsByState.forEach((state, count) ->
System.out.println(" " + state + ": " + count));
if (!deadlockedThreads.isEmpty()) {
System.out.println("\n🚨 Deadlocked threads:");
deadlockedThreads.forEach(thread ->
System.out.println(" " + thread));
}
if (!blockedOnResources.isEmpty()) {
System.out.println("\n🔒 Most contended resources:");
blockedOnResources.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
.limit(5)
.forEach(entry ->
System.out.println(" " + entry.getKey() + ": " +
entry.getValue() + " threads"));
}
if (!topStackFrames.isEmpty()) {
System.out.println("\n📊 Top stack frames:");
topStackFrames.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
.limit(10)
.forEach(entry ->
System.out.println(" " + entry.getKey() + ": " +
entry.getValue() + " threads"));
}
if (!suspiciousPatterns.isEmpty()) {
System.out.println("\n⚠️ Suspicious patterns detected:");
suspiciousPatterns.forEach(pattern ->
System.out.println(" " + pattern));
}
if (!threadNamePatterns.isEmpty()) {
System.out.println("\n🏷️ Thread name patterns:");
threadNamePatterns.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
.forEach(entry ->
System.out.println(" " + entry.getKey() + ": " +
entry.getValue() + " threads"));
}
}
}
public static AnalysisResult analyzeThreadDump(String filename) {
AnalysisResult result = new AnalysisResult();
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
String line;
String currentThread = null;
Thread.State currentState = null;
List<String> currentStackTrace = new ArrayList<>();
while ((line = reader.readLine()) != null) {
line = line.trim();
// 解析线程信息
if (line.startsWith("Thread: ")) {
// 处理前一个线程的信息
if (currentThread != null) {
processThreadInfo(result, currentThread, currentState, currentStackTrace);
}
// 开始新线程
currentThread = extractThreadName(line);
currentStackTrace.clear();
result.totalThreads++;
// 检查是否是死锁线程
if (line.contains("[DEADLOCKED]")) {
result.deadlockedThreads.add(currentThread);
}
} else if (line.startsWith("State: ")) {
currentState = parseThreadState(line);
if (currentState != null) {
result.threadsByState.put(currentState,
result.threadsByState.getOrDefault(currentState, 0) + 1);
}
} else if (line.startsWith("Blocked on: ")) {
String resource = extractResource(line);
if (resource != null) {
result.blockedOnResources.put(resource,
result.blockedOnResources.getOrDefault(resource, 0) + 1);
}
} else if (line.startsWith(" at ")) {
currentStackTrace.add(line.substring(5)); // 移除 " at "
// 记录栈帧
String method = extractMethodFromStackFrame(line);
if (method != null && !isSystemMethod(method)) {
result.topStackFrames.put(method,
result.topStackFrames.getOrDefault(method, 0) + 1);
}
}
}
// 处理最后一个线程
if (currentThread != null) {
processThreadInfo(result, currentThread, currentState, currentStackTrace);
}
} catch (IOException e) {
System.err.println("Error reading thread dump file: " + e.getMessage());
}
// 检测可疑模式
detectSuspiciousPatterns(result);
return result;
}
private static void processThreadInfo(AnalysisResult result, String threadName,
Thread.State state, List<String> stackTrace) {
// 分析线程名模式
String pattern = extractThreadNamePattern(threadName);
result.threadNamePatterns.put(pattern,
result.threadNamePatterns.getOrDefault(pattern, 0) + 1);
}
private static String extractThreadName(String line) {
// 提取 "Thread: name [DEADLOCKED]" 中的 name
Pattern pattern = Pattern.compile("Thread: ([^\\[]+)");
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
return matcher.group(1).trim();
}
return "Unknown";
}
private static Thread.State parseThreadState(String line) {
String stateStr = line.substring("State: ".length()).trim();
try {
return Thread.State.valueOf(stateStr);
} catch (IllegalArgumentException e) {
return null;
}
}
private static String extractResource(String line) {
// 提取 "Blocked on: java.lang.Object@1a2b3c4d" 中的资源类型
String resource = line.substring("Blocked on: ".length()).trim();
int atIndex = resource.indexOf('@');
if (atIndex > 0) {
return resource.substring(0, atIndex);
}
return resource;
}
private static String extractMethodFromStackFrame(String line) {
// 提取 " at com.example.Class.method(Class.java:123)" 中的方法
String frame = line.substring(5).trim(); // 移除 " at "
int parenIndex = frame.indexOf('(');
if (parenIndex > 0) {
return frame.substring(0, parenIndex);
}
return frame;
}
private static boolean isSystemMethod(String method) {
return method.startsWith("java.") ||
method.startsWith("javax.") ||
method.startsWith("sun.") ||
method.startsWith("com.sun.");
}
private static String extractThreadNamePattern(String threadName) {
// 提取线程名模式,如 "pool-1-thread-123" -> "pool-*-thread-*"
return threadName.replaceAll("\\d+", "*");
}
private static void detectSuspiciousPatterns(AnalysisResult result) {
// 检测大量BLOCKED线程
int blockedCount = result.threadsByState.getOrDefault(Thread.State.BLOCKED, 0);
if (blockedCount > result.totalThreads * 0.3) {
result.suspiciousPatterns.add(
String.format("High number of BLOCKED threads: %d (%.1f%%)",
blockedCount, (double)blockedCount / result.totalThreads * 100));
}
// 检测大量WAITING线程
int waitingCount = result.threadsByState.getOrDefault(Thread.State.WAITING, 0);
if (waitingCount > result.totalThreads * 0.5) {
result.suspiciousPatterns.add(
String.format("High number of WAITING threads: %d (%.1f%%)",
waitingCount, (double)waitingCount / result.totalThreads * 100));
}
// 检测线程池饱和
for (Map.Entry<String, Integer> entry : result.threadNamePatterns.entrySet()) {
if (entry.getKey().contains("pool") && entry.getValue() > 50) {
result.suspiciousPatterns.add(
String.format("Large thread pool detected: %s (%d threads)",
entry.getKey(), entry.getValue()));
}
}
// 检测热点资源
for (Map.Entry<String, Integer> entry : result.blockedOnResources.entrySet()) {
if (entry.getValue() > 10) {
result.suspiciousPatterns.add(
String.format("Resource contention hotspot: %s (%d threads blocked)",
entry.getKey(), entry.getValue()));
}
}
}
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Usage: java ThreadDumpAnalyzer <thread_dump_file>");
return;
}
String filename = args[0];
AnalysisResult result = analyzeThreadDump(filename);
result.printSummary();
}
}
5. 实践练习
5.1 练习1:线程状态监控
目标:创建一个多线程应用,观察不同线程状态的变化。
// 线程状态监控练习
public class ThreadStateMonitoringExercise {
private static final Object sharedLock = new Object();
private static volatile boolean running = true;
public static void main(String[] args) throws InterruptedException {
System.out.println("=== Thread State Monitoring Exercise ===");
System.out.println("启动多个不同状态的线程,使用 VisualVM 观察线程状态变化");
// 1. RUNNABLE 状态线程(CPU密集型)
Thread cpuIntensive = new Thread(() -> {
while (running) {
// 执行计算密集型任务
double result = 0;
for (int i = 0; i < 100000; i++) {
result += Math.sqrt(i);
}
}
}, "CPU-Intensive-Thread");
// 2. TIMED_WAITING 状态线程
Thread sleepingThread = new Thread(() -> {
while (running) {
try {
Thread.sleep(2000);
System.out.println("Sleeping thread woke up");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "Sleeping-Thread");
// 3. WAITING 状态线程
Thread waitingThread = new Thread(() -> {
synchronized (sharedLock) {
try {
while (running) {
sharedLock.wait();
System.out.println("Waiting thread was notified");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "Waiting-Thread");
// 4. BLOCKED 状态线程
Thread blockedThread1 = new Thread(() -> {
while (running) {
synchronized (sharedLock) {
try {
Thread.sleep(1000);
System.out.println("Blocked thread 1 holding lock");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "Blocked-Thread-1");
Thread blockedThread2 = new Thread(() -> {
while (running) {
synchronized (sharedLock) {
try {
Thread.sleep(1000);
System.out.println("Blocked thread 2 holding lock");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "Blocked-Thread-2");
// 启动所有线程
cpuIntensive.start();
sleepingThread.start();
waitingThread.start();
blockedThread1.start();
blockedThread2.start();
// 定期唤醒等待线程
Thread notifierThread = new Thread(() -> {
while (running) {
try {
Thread.sleep(5000);
synchronized (sharedLock) {
sharedLock.notify();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "Notifier-Thread");
notifierThread.start();
System.out.println("\n线程已启动,请在 VisualVM 中观察线程状态:");
System.out.println("1. 打开 VisualVM");
System.out.println("2. 连接到当前 Java 进程");
System.out.println("3. 切换到 Threads 标签页");
System.out.println("4. 观察不同颜色的线程状态变化");
System.out.println("\n按 Enter 键停止程序...");
System.in.read();
// 停止所有线程
running = false;
// 唤醒等待线程以便正常退出
synchronized (sharedLock) {
sharedLock.notifyAll();
}
// 等待所有线程结束
cpuIntensive.interrupt();
sleepingThread.interrupt();
waitingThread.interrupt();
blockedThread1.interrupt();
blockedThread2.interrupt();
notifierThread.interrupt();
System.out.println("程序已停止");
}
}
5.2 练习2:死锁检测与分析
目标:创建死锁场景,使用 VisualVM 检测和分析死锁。
// 死锁检测练习
public class DeadlockDetectionExercise {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
private static final Object lock3 = new Object();
public static void main(String[] args) throws InterruptedException {
System.out.println("=== Deadlock Detection Exercise ===");
System.out.println("创建死锁场景,使用 VisualVM 检测死锁");
// 场景1:简单的两线程死锁
createSimpleDeadlock();
Thread.sleep(2000);
// 场景2:复杂的三线程循环死锁
createComplexDeadlock();
System.out.println("\n死锁已创建,请在 VisualVM 中检测:");
System.out.println("1. 在 Threads 标签页中查看死锁警告");
System.out.println("2. 点击 'Thread Dump' 按钮生成线程转储");
System.out.println("3. 分析死锁循环链");
System.out.println("4. 查看每个死锁线程的栈跟踪");
// 启动死锁监控
DeadlockDetector detector = new DeadlockDetector();
detector.startContinuousMonitoring(5);
// 保持程序运行
Thread.sleep(Long.MAX_VALUE);
}
private static void createSimpleDeadlock() {
Thread thread1 = new Thread(() -> {
synchronized (lock1) {
System.out.println("Simple-Thread-1: Got lock1");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Simple-Thread-1: Trying to get lock2...");
synchronized (lock2) {
System.out.println("Simple-Thread-1: Got both locks");
}
}
}, "Simple-Deadlock-Thread-1");
Thread thread2 = new Thread(() -> {
synchronized (lock2) {
System.out.println("Simple-Thread-2: Got lock2");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Simple-Thread-2: Trying to get lock1...");
synchronized (lock1) {
System.out.println("Simple-Thread-2: Got both locks");
}
}
}, "Simple-Deadlock-Thread-2");
thread1.start();
thread2.start();
}
private static void createComplexDeadlock() {
Thread threadA = new Thread(() -> {
synchronized (lock1) {
System.out.println("Complex-Thread-A: Got lock1");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
synchronized (lock2) {
System.out.println("Complex-Thread-A: Got lock2");
}
}
}, "Complex-Deadlock-Thread-A");
Thread threadB = new Thread(() -> {
synchronized (lock2) {
System.out.println("Complex-Thread-B: Got lock2");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
synchronized (lock3) {
System.out.println("Complex-Thread-B: Got lock3");
}
}
}, "Complex-Deadlock-Thread-B");
Thread threadC = new Thread(() -> {
synchronized (lock3) {
System.out.println("Complex-Thread-C: Got lock3");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
synchronized (lock1) {
System.out.println("Complex-Thread-C: Got lock1");
}
}
}, "Complex-Deadlock-Thread-C");
threadA.start();
threadB.start();
threadC.start();
}
}
5.3 练习3:线程转储分析
目标:生成和分析线程转储文件。
// 线程转储分析练习
public class ThreadDumpAnalysisExercise {
public static void main(String[] args) throws InterruptedException {
System.out.println("=== Thread Dump Analysis Exercise ===");
// 创建各种线程场景
createVariousThreadScenarios();
// 等待线程启动
Thread.sleep(2000);
// 生成线程转储
String dumpFile = "exercise_thread_dump.txt";
ThreadDumpGenerator.generateThreadDump(dumpFile);
// 分析线程转储
System.out.println("\n分析线程转储文件...");
ThreadDumpAnalyzer.AnalysisResult result =
ThreadDumpAnalyzer.analyzeThreadDump(dumpFile);
result.printSummary();
System.out.println("\n练习完成!请查看生成的线程转储文件: " + dumpFile);
}
private static void createVariousThreadScenarios() {
// 创建多种线程场景用于分析
// 1. 线程池场景
java.util.concurrent.ExecutorService executor =
java.util.concurrent.Executors.newFixedThreadPool(10);
for (int i = 0; i < 20; i++) {
final int taskId = i;
executor.submit(() -> {
try {
Thread.sleep(10000 + (int)(Math.random() * 5000));
System.out.println("Task " + taskId + " completed");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
// 2. 生产者-消费者场景
java.util.concurrent.BlockingQueue<String> queue =
new java.util.concurrent.ArrayBlockingQueue<>(5);
// 生产者
for (int i = 0; i < 3; i++) {
final int producerId = i;
new Thread(() -> {
int count = 0;
while (true) {
try {
queue.put("Item-" + producerId + "-" + (++count));
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "Producer-" + i).start();
}
// 消费者
for (int i = 0; i < 2; i++) {
final int consumerId = i;
new Thread(() -> {
while (true) {
try {
String item = queue.take();
Thread.sleep(200);
System.out.println("Consumer-" + consumerId + " processed: " + item);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "Consumer-" + i).start();
}
// 3. 锁竞争场景
Object contentionLock = new Object();
for (int i = 0; i < 5; i++) {
final int threadId = i;
new Thread(() -> {
while (true) {
synchronized (contentionLock) {
try {
Thread.sleep(50);
// 模拟工作
for (int j = 0; j < 1000; j++) {
Math.sqrt(j);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "Contention-Thread-" + i).start();
}
}
}
6. 本章总结
6.1 关键要点
-
线程状态理解:
- 掌握 Java 线程的六种状态及其转换条件
- 理解每种状态在 VisualVM 中的颜色表示
- 能够通过线程状态分析应用程序的行为模式
-
VisualVM 线程监控:
- 熟练使用 Threads 标签页进行实时监控
- 理解线程时间线图表的含义
- 能够分析线程详细信息和栈跟踪
-
死锁检测与分析:
- 理解死锁的四个必要条件
- 掌握使用 VisualVM 检测死锁的方法
- 能够分析死锁循环链和解决方案
-
线程转储分析:
- 了解如何生成和分析线程转储文件
- 掌握自动化分析工具的使用
- 能够识别常见的线程问题模式
6.2 最佳实践
-
监控策略:
- 定期监控线程状态分布
- 关注异常的线程状态模式
- 建立线程监控告警机制
-
死锁预防:
- 实施锁排序策略
- 使用超时锁机制
- 避免嵌套锁的使用
-
性能优化:
- 识别线程瓶颈和热点
- 优化锁竞争和等待时间
- 合理配置线程池大小
-
故障诊断:
- 保存关键时刻的线程转储
- 建立线程问题的诊断流程
- 使用自动化工具进行分析
6.3 下一步学习
在下一章中,我们将学习:
- 内存分析与堆转储:深入了解 Java 内存结构和垃圾回收
- 堆转储生成与分析:掌握内存泄漏检测技巧
- 对象引用分析:理解对象生命周期和内存占用
- 内存优化策略:学习内存调优的最佳实践
通过本章的学习,你已经掌握了线程分析和死锁检测的核心技能,这为进一步的性能分析和优化奠定了坚实的基础。
更多推荐
所有评论(0)