← Назад к вопросам
Какие знаешь классы мониторинга для просмотра многопоточности?
2.0 Middle🔥 191 комментариев
#Многопоточность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Инструменты и классы мониторинга многопоточности в Java
Мониторинг многопоточности — это критически важный навык для диагностики проблем с конкурентностью, deadlock'ов и bottleneck'ов в высоконагруженных системах. Java предоставляет мощные встроенные инструменты для этого.
1. Встроенные JDK инструменты
jps (Java Process Status)
# Получить ID всех Java процессов
jps -l
# Пример выхода:
# 12345 com.example.Application
# 12346 org.springframework.boot.loader.JarLauncher
jstack (Java Stack Trace)
# Получить stack trace для процесса
jstack 12345 > thread-dump.txt
# Пример вывода:
# "main" #1 prio=5 os_prio=0 tid=0x00007f8b8a00c800 nid=0x3e9c runnable
# java.lang.Thread.State: RUNNABLE
# at java.io.FileInputStream.readBytes(Native Method)
# at java.io.FileInputStream.read(FileInputStream.java:255)
jcmd (JVM Diagnostic Command Tool)
# Список всех доступных команд
jcmd 12345 help
# Dump потоков
jcmd 12345 Thread.print
# Информация о блокировках
jcmd 12345 VM.info
2. Класс java.lang.Thread для мониторинга
public class ThreadMonitoring {
public static void analyzeThreads() {
ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parent;
// Найти корневую группу потоков
while ((parent = rootGroup.getParent()) != null) {
rootGroup = parent;
}
// Получить информацию обо всех потоках
Thread[] threads = new Thread[rootGroup.activeCount()];
rootGroup.enumerate(threads);
System.out.println("Активных потоков: " + threads.length);
for (Thread thread : threads) {
if (thread != null) {
System.out.println("\nПоток: " + thread.getName());
System.out.println(" ID: " + thread.getId());
System.out.println(" Приоритет: " + thread.getPriority());
System.out.println(" Состояние: " + thread.getState());
System.out.println(" Живой: " + thread.isAlive());
System.out.println(" Daemon: " + thread.isDaemon());
// Stack trace
StackTraceElement[] stackTrace = thread.getStackTrace();
for (StackTraceElement element : stackTrace) {
System.out.println(" " + element);
}
}
}
}
}
3. ThreadMXBean — управление потоками через JMX
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
public class ThreadMXBeanMonitor {
public static void monitorThreads() {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// Общая информация
System.out.println("Всего потоков: " + threadMXBean.getThreadCount());
System.out.println("Пиковое количество: " + threadMXBean.getPeakThreadCount());
System.out.println("Daemon потоков: " + threadMXBean.getDaemonThreadCount());
System.out.println("Всего созданных: " + threadMXBean.getTotalStartedThreadCount());
}
public static void detectDeadlock() {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// Найти deadlock'и
long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();
if (deadlockedThreads != null && deadlockedThreads.length > 0) {
System.out.println("НАЙДЕН DEADLOCK!");
System.out.println("Потоки в deadlock'е: " + deadlockedThreads.length);
java.lang.management.ThreadInfo[] threadInfos =
threadMXBean.getThreadInfo(deadlockedThreads);
for (java.lang.management.ThreadInfo threadInfo : threadInfos) {
System.out.println("\nПоток: " + threadInfo.getThreadName());
System.out.println("Состояние: " + threadInfo.getThreadState());
System.out.println("Заблокирован: " +
threadInfo.getLockName());
System.out.println("Владелец блокировки: " +
threadInfo.getLockOwnerName());
}
} else {
System.out.println("Deadlock'ов не найдено");
}
}
public static void monitorThreadContention() {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// Включить мониторинг блокировок
if (threadMXBean.isThreadContentionMonitoringSupported()) {
threadMXBean.setThreadContentionMonitoringEnabled(true);
long[] threadIds = threadMXBean.getAllThreadIds();
for (long threadId : threadIds) {
java.lang.management.ThreadInfo info =
threadMXBean.getThreadInfo(threadId);
if (info != null) {
System.out.println("\nПоток: " + info.getThreadName());
System.out.println("Время в блокировке (мс): " +
info.getBlockedTime());
System.out.println("Количество блокировок: " +
info.getBlockedCount());
System.out.println("Время ожидания (мс): " +
info.getWaitedTime());
System.out.println("Количество ожиданий: " +
info.getWaitedCount());
}
}
}
}
}
4. Мониторинг через JMX
import javax.management.*;
import java.lang.management.ManagementFactory;
public class JMXThreadMonitoring {
public static void setupJMXMonitoring() throws MalformedObjectNameException {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
// Получить ThreadMXBean через JMX
ObjectName threadBean = new ObjectName(
"java.lang:type=Threading");
try {
Object threadCount = mbs.getAttribute(threadBean, "ThreadCount");
System.out.println("Потоков: " + threadCount);
Object peakThreadCount = mbs.getAttribute(
threadBean, "PeakThreadCount");
System.out.println("Пиковое количество: " + peakThreadCount);
Object daemonThreadCount = mbs.getAttribute(
threadBean, "DaemonThreadCount");
System.out.println("Daemon потоков: " + daemonThreadCount);
} catch (AttributeNotFoundException e) {
System.out.println("Атрибут не найден: " + e.getMessage());
} catch (MBeanException | ReflectionException e) {
e.printStackTrace();
}
}
}
5. Встроенные инструменты профилирования
JVisualVM
# Запустить визуальный монитор
jvisualvm
# Графический интерфейс с информацией о потоках, памяти, CPU
Java Mission Control (JMC)
# Запустить JMC
jmc
# Мощный инструмент для профилирования с low overhead
6. Программное отслеживание производительности
public class PerformanceMonitor {
public static void monitorThreadPerformance() {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// Получить CPU время для текущего потока
long threadId = Thread.currentThread().getId();
long cpuTime = threadMXBean.getThreadCpuTime(threadId);
long userTime = threadMXBean.getThreadUserTime(threadId);
System.out.println("CPU время (нано): " + cpuTime);
System.out.println("User время (нано): " + userTime);
System.out.println("CPU время (мс): " + (cpuTime / 1_000_000));
}
public static void monitorLocks() throws Exception {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
long[] threadIds = threadMXBean.getAllThreadIds();
for (long threadId : threadIds) {
java.lang.management.ThreadInfo info =
threadMXBean.getThreadInfo(threadId, true, true);
if (info != null && info.getLockedMonitors().length > 0) {
System.out.println("\nПоток: " + info.getThreadName());
System.out.println("Удерживаемые блокировки:");
for (java.lang.management.MonitorInfo monitor :
info.getLockedMonitors()) {
System.out.println(" - " + monitor.getClassName() +
" @" + monitor.getIdentityHashCode());
}
}
}
}
}
7. Практический пример мониторинга
public class ThreadHealthMonitor implements Runnable {
private volatile boolean running = true;
@Override
public void run() {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
while (running) {
try {
// Периодический мониторинг
int threadCount = threadMXBean.getThreadCount();
long totalMemory = Runtime.getRuntime().totalMemory();
long freeMemory = Runtime.getRuntime().freeMemory();
System.out.printf("[%s] Потоков: %d | Память: %d MB / %d MB%n",
LocalTime.now(),
threadCount,
freeMemory / (1024 * 1024),
totalMemory / (1024 * 1024)
);
// Проверка на deadlock
long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();
if (deadlockedThreads != null && deadlockedThreads.length > 0) {
System.err.println("警告: Обнаружен deadlock!");
}
Thread.sleep(5000); // Проверять каждые 5 сек
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
}
8. Команды для анализа потоков
# Dump всех потоков в файл
jstack -F <pid> > dump.txt
# Анализ CPU usage по потокам
jps -l | grep Application | awk '{print $1}' | xargs jstack
# Мониторинг в реальном времени
jcmd <pid> Thread.print > /tmp/thread_dump_$(date +%s).txt
Таблица инструментов
| Инструмент | Назначение | Тип |
|---|---|---|
| jps | Список процессов | CLI |
| jstack | Dump потоков | CLI |
| jcmd | Диагностические команды | CLI |
| ThreadMXBean | Programmatic мониторинг | API |
| JVisualVM | GUI монитор | Визуальный |
| JMC | Профилирование | Визуальный |
| Micrometer | Metrics collection | Library |
| Prometheus | Monitoring system | System |
Заключение
Профессиональный Java разработчик должен хорошо разбираться в инструментах мониторинга многопоточности для быстрого выявления и решения проблем с конкурентностью, deadlock'ов и performance bottleneck'ов. Комбинация встроенных JDK инструментов (jstack, jcmd) и programmatic API (ThreadMXBean) позволяет эффективно диагностировать проблемы в production.