在Java多线程编程场景中,当需要排查线程死锁、长时间阻塞或者运行状态异常的问题时,获取线程的状态、堆栈信息和锁持有情况是核心的排查手段,ThreadInfo类就是专门用于封装这些线程相关信息的工具类,它属于java.lang.management包,能够通过ManagementFactory获取对应的线程管理实例后得到。

ThreadInfo的获取方式
要获取ThreadInfo实例,首先需要拿到ThreadMXBean对象,这是Java虚拟机线程系统的管理接口,通过ManagementFactory的静态方法即可获取,之后可以调用对应的方法得到指定线程ID或者所有线程的ThreadInfo信息。
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.lang.management.ThreadInfo;
public class ThreadInfoDemo {
public static void main(String[] args) {
// 获取线程管理Bean
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// 获取所有线程的ID
long[] threadIds = threadMXBean.getAllThreadIds();
// 获取所有线程的ThreadInfo,参数true表示获取锁信息,true表示获取堆栈信息
ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(threadIds, true, true);
// 遍历处理每个线程的ThreadInfo
for (ThreadInfo info : threadInfos) {
if (info != null) {
// 后续处理线程信息
}
}
}
}
通过ThreadInfo获取线程状态
ThreadInfo提供了getThreadState()方法,该方法会返回Thread.State枚举类型的线程状态,包含NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED六种状态,和Thread类本身的状态枚举完全一致。
同时还可以获取线程的基本属性,比如线程ID、线程名称、阻塞次数、等待次数等,这些属性能够辅助判断线程的运行情况。
// 获取线程状态
Thread.State state = info.getThreadState();
System.out.println("线程名称:" + info.getThreadName());
System.out.println("线程ID:" + info.getThreadId());
System.out.println("线程状态:" + state);
System.out.println("线程阻塞次数:" + info.getBlockedCount());
System.out.println("线程等待次数:" + info.getWaitedCount());
通过ThreadInfo获取线程堆栈信息
ThreadInfo的getStackTrace()方法会返回StackTraceElement数组,每个元素对应堆栈中的一层调用信息,包含类名、方法名、文件名以及行号,和我们通过Thread.getStackTrace()获取的内容一致。
可以通过遍历这个数组输出完整的调用堆栈,定位线程当前执行到的代码位置。
// 获取线程堆栈
StackTraceElement[] stackTrace = info.getStackTrace();
System.out.println("线程堆栈信息:");
for (StackTraceElement element : stackTrace) {
System.out.println("tat " + element.getClassName() + "." + element.getMethodName() + "(" + element.getFileName() + ":" + element.getLineNumber() + ")");
}
通过ThreadInfo获取锁相关信息
ThreadInfo提供了多个和锁相关的方法,能够获取线程持有的锁、等待的锁以及锁的持有者信息,是排查死锁和锁竞争问题的关键。
getLockedMonitors():返回线程持有的所有监视器锁对应的MonitorInfo数组getLockedSynchronizers():返回线程持有的所有可重入锁对应的LockInfo数组getLockName():如果线程处于BLOCKED状态,返回线程等待获取的锁的名称getLockOwnerId():返回持有当前线程等待的锁的线程ID,如果没有则返回-1getLockOwnerName():返回持有当前线程等待的锁的线程名称,如果没有则返回null
// 获取锁相关信息
String lockName = info.getLockName();
if (lockName != null) {
System.out.println("线程等待的锁:" + lockName);
System.out.println("锁持有者线程ID:" + info.getLockOwnerId());
System.out.println("锁持有者线程名称:" + info.getLockOwnerName());
}
// 获取持有的监视器锁
System.out.println("线程持有的监视器锁:");
for (MonitorInfo monitor : info.getLockedMonitors()) {
System.out.println("t锁名称:" + monitor.getLockedStackFrame());
}
// 获取持有的同步器锁
System.out.println("线程持有的同步器锁:");
for (LockInfo lock : info.getLockedSynchronizers()) {
System.out.println("t锁类名:" + lock.getClassName() + ",标识:" + lock.getIdentityHashCode());
}
完整示例:排查线程阻塞场景
下面是一个模拟线程阻塞的场景,通过ThreadInfo输出对应线程的状态、堆栈和锁信息,直观展示ThreadInfo的实际应用。
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.Thread.State;
public class BlockedThreadDemo {
private static final Object LOCK = new Object();
public static void main(String[] args) throws Exception {
// 启动一个持有锁的线程
Thread holderThread = new Thread(() -> {
synchronized (LOCK) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "LockHolderThread");
holderThread.start();
// 启动一个等待锁的线程
Thread blockedThread = new Thread(() -> {
synchronized (LOCK) {
System.out.println("获取锁成功");
}
}, "BlockedThread");
blockedThread.start();
// 等待线程启动后获取信息
Thread.sleep(1000);
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// 获取两个线程的ThreadInfo
ThreadInfo holderInfo = threadMXBean.getThreadInfo(holderThread.getId(), true, true);
ThreadInfo blockedInfo = threadMXBean.getThreadInfo(blockedThread.getId(), true, true);
// 输出持有锁线程的信息
System.out.println("===== 锁持有线程信息 =====");
System.out.println("线程状态:" + holderInfo.getThreadState());
System.out.println("持有的锁数量:" + holderInfo.getLockedMonitors().length);
// 输出阻塞线程的信息
System.out.println("n===== 阻塞线程信息 =====");
System.out.println("线程状态:" + blockedInfo.getThreadState());
System.out.println("等待的锁:" + blockedInfo.getLockName());
System.out.println("锁持有者线程ID:" + blockedInfo.getLockOwnerId());
}
}
运行上述代码后,可以看到锁持有线程处于TIMED_WAITING状态,阻塞线程处于BLOCKED状态,并且阻塞线程的锁信息中会显示等待的锁以及持有锁的线程ID,能够清晰定位线程阻塞的原因。
ThreadInfo线程状态堆栈信息锁信息修改时间:2026-06-13 10:57:17