1 ThreadGroup介绍
线程组代表一组线程。 此外,线程组还可以包括其他线程组。 线程组形成一个树,除了初始线程组之外,每个线程组都有一个父进程。
允许线程访问有关其线程组的信息,但不能访问有关其线程组的父线程组或任何其他线程组的信息。
在Thread的构造函数中,可以显式地指定线程的Group,也就是ThreadGroup。在线程的构造方法中的init方法中有这么一段:
if (g == null) {
// 如果没有明确指定线程组,就会采用父线程(创建当前线程的线程)的线程组
// 换句话说,就是会和父线程同属一个组
g = parent.getThreadGroup();
}
关于线程构造方法的可参考:深入理解Thread构造函数
- main线程所在的ThreadGroup称为main。
- 构造一个线程的时候如果没有显式地指定ThreadGroup,那么它将会和父线程同属于一个ThreadGroup。
- 同线程存在父子关系一样,ThreadGroup同样也存在父子关系
2 创建ThreadGroup
ThreadGroup的构造方法v
public ThreadGroup(String name)
/**
和上面的比,指定父线程组
**/
public ThreadGroup(ThreadGroup parent,String name)
-
如果不指定父线程组,默认的线程组就是创建它的线程所属的线程组:
public ThreadGroup(String name) { this(Thread.currentThread().getThreadGroup(), name); }
一个小测试代码: 验证上面的
public class Demo1 {
public static void main(String[] args) {
ThreadGroup threadGroup = new ThreadGroup("我的线程组1");
// 获取我的线程组1的父线程组: main
System.out.println(threadGroup.getParent().getName());
ThreadGroup threadGroup1 = new ThreadGroup(threadGroup,"我的线程组2");
// 获取我的线程组1的父线程组: 我的线程组1
System.out.println(threadGroup1.getParent().getName());
new Thread(threadGroup1,()->{
ThreadGroup threadGroup3 = new ThreadGroup("我的线程组3");
// 获取我的线程组1的父线程组: 我的线程组1
System.out.println(threadGroup3.getParent().getName());
}).start();
}
}
main
我的线程组1
我的线程组2
3 复制Thread数组和ThreadGroup数组
在一个ThreadGroup中会加入若干个线程以及子ThreadGroup,ThreadGroup为我们提供了若干个方法,可以复制出线程和线程组。
3.1 复制Thread数组
public int enumerate(Thread[] list)
public int enumerate(Thread[] list,boolean recurse)
述两个方法,会将ThreadGroup中的active线程全部复制到Thread数组中,其中recurse参数如果为true,则该方法会将所有子group中的active线程都递归到Thread数组中,enumerate(Thread[]list)实际上等价于enumerate(Thread[],true)
上面两个方法都调用了ThreadGroup的私有方法enumerate
- enumerate方法获取的线程仅仅是个预估值,并不能百分之百地保证当前group的活跃线程,比如在调用复制之后,某个线程结束了生命周期或者新的线程加入了进来,都会导致数据的不准确
- enumerate方法的返回值int相较Thread[]的长度更为真实,比如定义了数组长度的Thread数组,那么enumerate方法仅仅会将当前活跃的thread分别放进数组中,而返回值int则代表真实的数量,并非Thread数组的长度
3.2 复制ThreadGroup数组
public int enumerate(ThreadGroup[] list)
public int enumerate(ThreadGroup[] list,boolean recurse)
和复制Thread数组类似,上述两个方法,主要用于复制当前ThreadGroup的子Group,同样recurse会决定是否以递归的方式复制。