显示当前在JVM中运行的所有线程组和线程

时间:2017-10-26 16:47:38

标签: java multithreading jvm java-threads

所以我的任务是显示当前在JVM中运行的所有线程组和属于这些组的所有线程。

应输出此信息,以便首先显示线程组,然后显示该组中的所有踏板。这是针对所有线程组完成的。目前我的代码只显示每个线程组,然后显示每个线程,但我不确定如何达到我所描述的输出。

这是我目前的代码:

public  ThreadGroup getThreadRoot() {
    ThreadGroup rootGroup = Thread.currentThread( ).getThreadGroup( );
    ThreadGroup parentGroup;
    while ( ( parentGroup = rootGroup.getParent() ) != null ) {
        rootGroup = parentGroup;
    }
    return rootGroup;
}

public  ThreadGroup[] getAllThreadGroups(){


    ThreadGroup root= getThreadRoot();
    int estimate = root.activeGroupCount();
    ThreadGroup [] threads = new ThreadGroup[estimate];
    while ( root.enumerate( threads, true ) == threads.length ) {
        threads = new ThreadGroup[ threads.length * 2 ];
    }


    ThreadGroup[] allGroups = new ThreadGroup[threads.length+1];
    allGroups[0] = root;
    System.arraycopy( threads, 0, allGroups, 1, estimate );
    return allGroups;

}
public Thread[] getAllThreads(){

     ThreadGroup root= getThreadRoot();
     int estimate = root.activeGroupCount();
     Thread [] allThreads = new Thread[estimate];
     while ( root.enumerate( allThreads, true ) == allThreads.length ) {
         allThreads = new Thread[ allThreads.length * 2 ];
     }


     return allThreads;

}

和主要方法:

public static void main(String[] args)   {

    CreateDummyGroups create = new CreateDummyGroups();
    Functionality func = new Functionality();
    ThreadGroup[] tg = func.getAllThreadGroups();
    Thread[] t = func.getAllThreads();
    for (int i=0; i<tg.length; i++) {
        if(tg[i] != null){
        System.out.println("Name: " + tg[i].getName());
        }
    }
    for (int i=0; i<t.length; i++) {
        if(t[i] != null){
        System.out.println("Name: " + t[i].getName() + ", id: " + t[i].getId() 
                + ", State: " + t[i].getState() + ", Is daemon? " + t[i].isDaemon());
        }
}
}

}

2 个答案:

答案 0 :(得分:1)

首先,对于获得所有线程组和线程的分层输出的最简单的解决方案,您只需要getThreadRoot()方法:

Functionality func = new Functionality();
func.getThreadRoot().list();

但是,它甚至会打印层次结构而不是仅包含线程作为子项的组列表。为此,你必须嵌套你的循环,即

CreateDummyGroups create = new CreateDummyGroups();
Functionality func = new Functionality();
ThreadGroup[] tg = func.getAllThreadGroups();
Thread[] t = func.getAllThreads();
for(int i=0; i<tg.length; i++) {
    if(tg[i] != null) {
        System.out.println("Name: " + tg[i].getName());
        for(int j=0; j<t.length; j++) {
            if(t[j] != null && t[j].getThreadGroup() == tg[i]) {
            System.out.println("    Name: " + t[j].getName() + ", id: " + t[j].getId() 
                    + ", State: " + t[j].getState() + ", Is daemon? " + t[j].isDaemon());
            }
        }
    }
}

这在内循环中使用引用比较,仅显示当前组的线程。更有效的方法是首先只获取当前组的线程,即向Functionality添加方法:

public Thread[] getThreadsOf(ThreadGroup group) {
    int estimate = group.activeCount();
    Thread[] groupThreads = new Thread[estimate];
    while(group.enumerate( groupThreads, false ) == groupThreads.length) {
        groupThreads = new Thread[ groupThreads.length * 2 ];
    }
    return groupThreads;
}

并将来电者更改为

CreateDummyGroups create = new CreateDummyGroups();
Functionality func = new Functionality();
ThreadGroup[] tg = func.getAllThreadGroups();
for(int i=0; i<tg.length; i++) {
    if(tg[i] != null) {
        System.out.println("Name: " + tg[i].getName());
        Thread[] t = func.getThreadsOf(tg[i]);
        for(int j=0; j<t.length; j++) {
            if(t[j] != null) {
            System.out.println("    Name: " + t[j].getName() + ", id: " + t[j].getId() 
                    + ", State: " + t[j].getState() + ", Is daemon? " + t[j].isDaemon());
            }
        }
    }
}

顺便说一句,从Java 5开始,这可以很好地写成

CreateDummyGroups create = new CreateDummyGroups();
Functionality func = new Functionality();
for(ThreadGroup tg: func.getAllThreadGroups()) {
    if(tg != null) {
        System.out.println("Name: " + tg.getName());
        for(Thread t: func.getThreadsOf(tg)) {
            if(t != null) {
                System.out.println("    Name: " + t.getName() + ", id: " + t.getId() 
                    + ", State: " + t.getState() + ", Is daemon? " + t.isDaemon());
            }
        }
    }
}

但请注意,这些旧的enumerate方法非常气馁。它们不仅使用起来复杂,而且由于线程和组在处理它们时可能会发生变化,因此容易出错。在一个时间点制作单个快照时,它更简单,更可靠:

CreateDummyGroups create = new CreateDummyGroups();
Map<ThreadGroup, List<Thread>> map = new LinkedHashMap<>();
for(Thread thread: Thread.getAllStackTraces().keySet()) {
    List<Thread> list = map.get(thread.getThreadGroup());
    if(list == null) {
        list = new ArrayList<>();
        map.put(thread.getThreadGroup(), list);
    }
    list.add(thread);
}


for(Map.Entry<ThreadGroup,List<Thread>> groupEntry: map.entrySet()) {
    System.out.println("Name: " + groupEntry.getKey().getName());
    for(Thread thread: groupEntry.getValue()) {
        System.out.println("    Name: " + thread.getName() + ", id: " + thread.getId() 
            + ", State: " + thread.getState() + ", Is daemon? " + thread.isDaemon());
    }
}

使用Java 8功能时,这种逻辑变得更加简单:

CreateDummyGroups create = new CreateDummyGroups();
Map<ThreadGroup, List<Thread>> map = Thread.getAllStackTraces().keySet()
    .stream().collect(Collectors.groupingBy(Thread::getThreadGroup));


map.forEach((group,threadList) -> {
    System.out.println("Name: " + group.getName());
    threadList.forEach(thread -> 
        System.out.println("    Name: " + thread.getName() + ", id: " + thread.getId() 
            + ", State: " + thread.getState() + ", Is daemon? " + thread.isDaemon())
    );
});

答案 1 :(得分:0)

获取所有线程的一种替代方法是使用ThreadMXBean:

ThreadMXBean thbean = ManagementFactory.getThreadMXBean();
final long[] ids = thbean.getAllThreadIds();

从那里您可以获得各种信息,另请参见:

https://github.com/liguobing/ToolCode/blob/master/ThreadUtilities.java

但是不幸的是,ThreadMXBean不能直接在Android上使用。