所以我的任务是显示当前在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());
}
}
}
}
答案 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上使用。