Получение информации о группе потоков для каждого потока - PullRequest
2 голосов
/ 27 мая 2020

У меня есть дамп потока, и в этом дампе потока каждый поток отображается в формате, как показано ниже:

"isThreadCpuTimeSupported": "true",
"getLockOwnerName": null,
"isSuspended": "false",
"stacktrace": "java.base@11.0.5/java.net.PlainSocketImpl.accept0(Native 
"cpuTime": "36359.375",
"userTime": "25828.125",
"threadState": "RUNNABLE",
"id": "1",
"lockName": null,
"threadName": "main",
"isNative": "true"

Мое требование - получить threadGroup каждого потока. Как я могу получи? Нужно ли мне сначала добавить их в группу потоков? Как мне узнать, входят ли они в группу потоков? На веб-сайте Fastthread.io когда я загружаю дамп потока, он автоматически находит группу потоков, как это сделать?

На стороне сервера я делаю что-то вроде этого, чтобы получить дамп потока:

ThreadMXBean tmbean = ManagementFactory.getThreadMXBean();
List<HashMap> list = new ArrayList<>();
long[] tids;
ThreadInfo[] tinfos;
tids = tmbean.getAllThreadIds();
tinfos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE);

for (ThreadInfo ti : tinfos) {
    try {
        list.add( printThreadInfo(ti,tmbean,response ));
    } catch (IOException ex) {
        _logger.error("could not call printThreadInfo",ex);
    }
}
...
...

и для каждого ti

map.put("threadName", ti.getThreadName());

Ответы [ 2 ]

3 голосов
/ 27 мая 2020

Как упоминал Сарел Фойерлихт, ThreadInfo не содержит информации о ThreadGroup. Мы можем использовать Thread#getThreadGroup() для получения информации о группе, выполнив следующие шаги:

  1. Получите верхнюю часть ThreadGroup, см. Ответ справки [ 1 ]
  2. Итерируйте Thread и подпрограмму ThreadGroup рекурсивно, чтобы получить сопоставление между Thread и соответствующим ThreadGroup, см. Ссылку [ 2 ] для связи между Thread и ThreadGroup

Следующая программа демонстрирует описанные выше шаги.


import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.HashMap;
import java.util.Map;

public class ThreadDumpWithGroup {
    public static void main(String args[]) {
        ThreadGroup top = getTopThreadGroup();
        Map<Long, String> threadIdToThreadGroupNameMap = new HashMap<>();
        putThreadIdToThreadGroupNameMap(top, threadIdToThreadGroupNameMap);
        ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
        long[] threadIds;
        ThreadInfo[] threadInfos;
        threadIds = threadBean.getAllThreadIds();
        threadInfos = threadBean.getThreadInfo(threadIds, Integer.MAX_VALUE);
        for (ThreadInfo threadInfo : threadInfos) {
            // May still be null as there may be new thread after constructing the map.
            String threadGroupName = threadIdToThreadGroupNameMap.get(threadInfo.getThreadId());
            String threadName = threadInfo.getThreadName();
            long threadId = threadInfo.getThreadId();
            System.out.println(
                    String.format("Group:%s, Thread Name:%s, Thread Id:%d", threadGroupName, threadName, threadId));
        }
    }

    /**
     * Result maybe inaccurate, see
     * {@link java.lang.ThreadGroup#enumerate(Thread[], boolean) enumerate}
     * {@link java.lang.ThreadGroup#enumerate(ThreadGroup[], boolean) enumerate}
     **/
    private static void putThreadIdToThreadGroupNameMap(ThreadGroup group,
            Map<Long, String> threadIdToThreadGroupNameMap) {
        Thread[] threads = new Thread[group.activeCount()];
        group.enumerate(threads, false);
        for (Thread thread : threads) {
            if (thread == null) {
                continue;
            }
            threadIdToThreadGroupNameMap.put(thread.getId(), group.getName());
        }

        ThreadGroup[] subGroups = new ThreadGroup[group.activeGroupCount()];
        group.enumerate(subGroups, false);
        for (ThreadGroup subGroup : subGroups) {
            putThreadIdToThreadGroupNameMap(subGroup, threadIdToThreadGroupNameMap);
        }
    }

    private static ThreadGroup getTopThreadGroup() {
        ThreadGroup top = Thread.currentThread().getThreadGroup();
        ThreadGroup parent;
        do {
            parent = top.getParent();
            if (parent != null) {
                top = parent;
            }
        } while (parent != null);
        return top;
    }
}

Ссылки
Получить список всех потоков, выполняющихся в данный момент в Java
Java 101: Понимание Java потоков, Часть 4: Группы потоков, волатильность и локальные переменные потока
Java Do c Группа потоков

3 голосов
/ 27 мая 2020

информация о группе потоков не является частью ThreadInfo см. https://bugs.openjdk.java.net/browse/JDK-8023908

вы можете получить ее из самого объекта потока t.getThreadGroup()

Fastthread.io вероятно, используя это имя, поскольку каждый пул потоков используется для присвоения имени с шаблоном, чтобы они могли группировать потоки с таким же именем, что и группа (эти группы, вероятно, не имеют функций объекта ThreadGroup, как в https://docs.oracle.com/javase/7/docs/api/java/lang/ThreadGroup.html)

как они сказали (fastthread с использованием имени групповых потоков): https://www.perfmatrix.com/fastthread-thread-dump-analyzer/ enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...