10年世界杯冠军_梅西2018年世界杯 - kefulq.com

一个 IDEA 老鸟的 DEBUG 私货之多线程调试

直播女篮世界杯 2025-10-04 04:44:34

总结一些 IDEA 好用的技巧。本篇介绍多线程的调试。

> IntelliJ IDEA 2024

一、IDEA 多线程调试要点

多线程调试,需要先掌握以下两个核心要点。

要点一:查看运行栈帧 && 切换线程

在 Threads & Variables 这个窗口,进行线程之间切换。

要点二:断点暂停方式,选择 Thread

这个是最为重要的。

建议多线程调试:选择 Make Default,点击图中 Make Default,后续所有断点都是 Thread,如果不选择 Thread,则无法进行线程断点追踪!所有线程将直接运行结束。

二、 多线程调试案例

本篇以 AQS 为案例,讲解多线程的调试过程。

ABC 三个线程,共同争夺一把锁获得锁后执行 count++完成后释放锁

具体代码如下:可以拷贝到自己的 IDEA 中进行体验

import java.util.concurrent.locks.ReentrantLock;

public class LockExample {

// ABC 三个线程抢夺一把锁。显示指明使用非公平锁

private static final ReentrantLock lock = new ReentrantLock(false);

// 获取锁后对 count 进行++ 操作

private static volatile int count = 0;

public static void main(String[] args) throws InterruptedException {

// 线程 A

Thread a = new Thread(() -> {

for (int i = 0; i < 10; i++) {

// 获取锁

lock.lock();

try {

count++;

System.out.println(Thread.currentThread().getName() + " incremented count to " + count);

} finally {

// 释放锁

lock.unlock();

}

}

}, "A");

// 线程 B

Thread b = new Thread(() -> {

for (int i = 0; i < 10; i++) {

// 抢占锁

lock.lock();

try {

count++;

System.out.println(Thread.currentThread().getName() + " incremented count to " + count);

} finally {

lock.unlock();

}

}

}, "B");

// 线程 B

Thread c = new Thread(() -> {

for (int i = 0; i < 10; i++) {

// 抢占锁

lock.lock();

try {

count++;

System.out.println(Thread.currentThread().getName() + " incremented count to " + count);

} finally {

lock.unlock();

}

}

}, "C");

a.start();

// 先让 B 线程晚一点执行

System.out.println("---------");

Thread.sleep(20000);

b.start();

// C 线程最后执行

System.out.println("---------");

Thread.sleep(20000);

c.start();

a.join();

b.join();

c.join();

}

}

模拟 ABC 三个线程抢锁过程,分别是 A 先抢到锁,然后 B、 C 再进入抢锁。 即三个线程运行。

2.1 模拟线程 A 执行

注意在 B、C 开始的位置设置断点,这样能够控制 B、C 线程的启动时间。

通过栈帧切换,就能执行线程 A 的所有相关逻辑了。

2.2 模拟线程 B 执行

先切换到 main 线程,启动线程 B; 当线程 B 启动后,切换到线程 B, 断点调试执行线程 B 的抢占过程。

步骤一:切换 main 线程,让线程 B 运行。

步骤二:当线程 B 运行成功后,切换线程 B,进行断点追踪。

当切换到 B 线程后,就能在 B 线程进行调试了。C 线程的逻辑类似。

最后,可以通过这种方式,查看 AQS 的锁队列情况。比如执行了两个线程后, AQS 中的同步队列器的状态如下所示。

细节可以自行探索, 本文不过多介绍了。

IDEA 在 Debug 时默认阻塞级别是 all,会阻塞其它线程,只有在当前调试线程走完时才会走其它线程; Thread 模式在 Remote 调试时不阻塞他人请求

三、小结

可以配合条件断点和日志来缩小范围,提高调试效率。打印线程名称等方式来掌握各个线程状态, 多线程下日志的打印也是一个非常好的方式evaluate Expression 计算表达式可以执行输入的代码,查看表达式的值,调用系统函数等。

调试多线程程序是一个复杂且需要耐心和技巧的任务,通过不断实践和学习,从而更好地应对多线程程序的挑战。

本文已经同步发布微信公众号:面汤放盐