一、 单个线程的 trace调用链 结构(流程图形式)
核心:只聚焦1个线程,只有「方法调用顺序」,无其他线程/状态信息
【车载音乐APP - 播放线程(Thread-Play)】
运行状态:RUNNABLE
↓
com.car.music.MediaPlayer.play() // 入口方法
↓
com.car.music.AudioDecoder.decode() // 解码方法
↓
com.car.music.FileReader.read() // 读取音频文件
↓
java.io.FileInputStream.read() // JDK底层方法
特点 :像一条「单线程执行路线图」,只告诉你这个线程从哪来、走到哪,适合定位单个方法的执行卡顿点。
二、 Get thread dump 的完整结构(多线程+状态+调用链)
核心:所有线程的快照总和 = 「N个线程的trace调用链」 + 「线程状态+锁信息」
【进程总览:车载APP进程(com.car.app) - 共12个线程】
1. 【主线程(UI Thread)】
状态:WAITING // 等待锁
持有锁:com.car.music.Lock@123 // 关键!持有解码锁
调用链:
android.app.Activity.onResume()
↓
com.car.music.MainActivity.updateUI()
2. 【播放线程(Thread-Play)】 // 上面trace的那个线程
状态:BLOCKED // 被阻塞!
等待锁:com.car.music.Lock@123 // 等的就是主线程持有的锁
调用链:
com.car.music.MediaPlayer.play()
↓
com.car.music.AudioDecoder.decode() // 卡在这一步等锁
↓
com.car.music.FileReader.read()
3. 【后台线程(Thread-Background)】
状态:RUNNABLE
调用链:
com.car.music.DownloadTask.run()
↓
java.net.HttpURLConnection.getInputStream()
特点 :像一张「整个APP的线程作战图」,不仅有每个线程的调用链,还能看到谁卡了谁、谁拿了锁,直接定位死锁/多线程冲突。
三、 核心区别对比表(一目了然)
| 维度 | trace调用链 | Get thread dump |
|---|---|---|
| 信息范围 | 单个线程的方法调用顺序 | 所有线程的「调用链+状态+锁+优先级」 |
| 核心用途 | 定位单个方法的执行流程/卡顿点 | 定位死锁、线程阻塞、多线程资源竞争问题 |
| 调试场景举例 | 音乐播放时,解码方法为啥执行慢? | 音乐播放卡住,是哪个线程抢了锁导致的? |
| 信息完整度 | 单一、局部 | 全面、全局 |
四、 调试时的使用流程(什么时候用哪个?)
发现车载APP播放卡顿 →
第一步:先抓【播放线程的trace】→ 看是不是解码方法本身慢 →
→ 若是,优化解码逻辑;
→ 若不是(比如卡在decode()不动),第二步:抓【thread dump】→ 看播放线程状态是不是BLOCKED → 查谁持有锁 → 解决锁冲突