参考网页
https://www.cnblogs.com/yiwangzhibujian/p/6212104.html
http://www.cnblogs.com/hvicen/p/6218981.html
例子代码
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
public class MultiThread {
public static void main(String[] args) {
// 获取 Java 线程管理 MXBean
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
//不需要获取同步的 monitor 和 synchronizer 信息,仅获取线程和线程堆栈信息
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
//遍历线程信息,仅打印线程id和线程名称信息
for (ThreadInfo threadInfo : threadInfos) {
System.out.println("[" + threadInfo.getThreadId() + "] " + threadInfo.getThreadName());
}
}
}
打印结果
[8] JDWP Command Reader
[7] JDWP Event Helper Thread
[6] JDWP Transport Listener: dt_socket
[5] Attach Listener
[4] Signal Dispatcher
[3] Finalizer
[2] Reference Handler
[1] main
代码分析
ThreadMXBean类
线程管理类,通过此类可以获取线程信息数组。
ManagementFactory类
管理工厂类,可以获取线程管理类对象ThreadMXBean。
打印结果分析
从打印结果可以看出,虽然面上只看到main线程,但是实际上Java程序中启动了很多线程。
- main //main线程,用户线程入口
- Reference Handler //清除Reference即引用对象的线程
- Finalizer //调用对象finalize方法的线程
- Signal Dispatcher //分发处理发送给JVM信号的线程
以上还都是默认的系统线程,如果代码中有用户自己创建的Thread,那么将会有更多的线程。
用户主线程的入口是main()静态方法,子线程的入口是Thread的run()方法。
★从用户角度讲开启多线程:主线程的入口是main()静态方法,子线程的入口是Thread的run()方法
★main方法执行后,将自动创建system线程组合main线程组,main方法所在线程存放在main线程组中
示例代码
public class ThreadGroupDemo {
public static void main(String[] args) {
Thread thread1 = new Thread("my thread1") {
public void run() {
Object lock = new Object();
synchronized(lock){
try {
lock.wait();
} catch (InterruptedException e) {
// e.printStackTrace();
}
}
}
};
thread1.start();
Thread thread2 = new Thread(new ThreadGroup("my group"), "my thread2") {
public void run() {
Object lock = new Object();
synchronized(lock){
try {
lock.wait();
} catch (InterruptedException e) {
// e.printStackTrace();
}
}
}
};
thread2.start();
ThreadGroup group = Thread.currentThread().getThreadGroup();
while (group.getParent() != null)
group = group.getParent();
group.list();
thread1.interrupt();
thread2.interrupt();
}
}
打印结果
java.lang.ThreadGroup[name=system,maxpri=10]
Thread[Reference Handler,10,system]
Thread[Finalizer,8,system]
Thread[Signal Dispatcher,9,system]
Thread[Attach Listener,5,system]
java.lang.ThreadGroup[name=main,maxpri=10]
Thread[main,5,main]
Thread[Monitor Ctrl-Break,5,main]
Thread[my thread1,5,main]
java.lang.ThreadGroup[name=my group,maxpri=10]
Thread[my thread2,5,my group]
打印结果分析
其实可以看出来,ThreadGroup是有层级关系的。main线程所在的ThreadGroup是在名为system的ThreadGroup下面的。
线程分组ThreadGroup,是一个线程集合,同时也是一个树节点,相当于文件夹,里面可以存放文件和子文件夹。
名为main的ThreadGroup就在名为system的ThreadGroup下面。或者可以认为名为main的ThreadGroup是名为system的ThreadGroup的【子文件夹】。同理,名为my group的ThreadGroup可以认为是名为main的ThreadGroup的【子文件夹】。
运行结果的分组与线程信息如下图所示:
system分组就是一个根线程组,其下就是main分组,main分组就是包含主线程的分组。
线程在创建时,可以选择提供线程组,未提供时就会使用默认的线程组,默认线程组的提供策略由SecurityManager#getThreadGroup()决定,而默认的提供策略为创建时当前线程所属的线程组。
ThreadGroup#list()方法
打印出根线程组下的线程和子线程组信息。