结构思维导图:
构造方法:
public ThreadGroup(String name);//为此线程组赋予名字,但该组的父线程组是创建它的线程所在的线程组
public ThreadGroup(ThreadGroup parent,String name);//第二个构造赋予了线程组名字,同时又显示的指定了组的父线程组
public static void main(String[] args) {
ThreadGroup currentGp = Thread.currentThread().getThreadGroup();//当前线程组
ThreadGroup gp = new ThreadGroup("GP1");
System.out.println(gp.getParent()==currentGp);//true gp没显示的指定父线程组,默认为创建它线程所在的线程组
ThreadGroup gp2 = new ThreadGroup(gp,"GP2");//指定gp为该组的父线程组
System.out.println(gp2.getParent() == gp);//true
}
复制ThreadGroup数组:
public int enumerate(ThreadGroup[] list);会将ThreadGroup中的active线程全部复制到Thread数组,等价于(Thread[] true)
public int enumerate(ThreadGroup list,boolean,recurse);会将所有的子group中的active线程递归到Thread数组中
public static void main(String[] args){
ThreadGroup gp1 = new ThreadGroup("gp1");//父线程是mainGroup
ThreadGroup gp2 = new ThreadGroup(gp1,"gp2");//父线程是gp1
TimeUnit.MILLSECONDS.Sleep(2);
ThreadGroup mainGroup = Thread.currentThread.getThreadGroup();
ThreadGroup[] list = new ThreadGroup[mainGroup.activeGroupCount()];
System.out.println(mainGroup.enumerate(list));//递归复制 2 包含了子类的子类
System.out.println(mainGroup.enumerate(list,false));//1
}
ThreadGroup的基本操作:
1、activeCount()用于获取group中的活跃线程,这只是估值,并不能百分百的保证数字一定正确(递归方法会获取所有的字group)
2、activeGroupCount()用于获取group中的活跃字group,这也是一个估值(该方法会递归所有的子group)
3、getMaxPriority()用于获取group的优先级,默认情况下优先级为10,在group中所有的线程的优先级都不能大于group的优先级
4、getName()获取group名字;getParent()获取group的父group,如果不存在返回null;list()该方法没有返回值执行该方法会将group中所有的活跃的线程信息输出到控制台
5、parentOf(ThreadGroup gp),判断当前group是不是给定group的父group,如果是自己返回true
6、setMaxPrioty(int pri) 会指定group的最大优先级,最大优先级不能超过父group的最大优先级,执行该方法不仅会改变当前group的最大优先级,还会改变所有字group的最大优先级
public static void main(String[] args) throws InterruptedException{
ThreadGroup gp = new ThreadGroup("gp1");//该组的父组是创建线程所在的父组,当然也可以显示指定父组(mainGp)
Thread thread = new Thread(gp,() -> {
while (true){
try {
TimeUnit.SECONDS.sleep(3);
}catch (InterruptedException e){
e.printStackTrace();
}
}
},"thread");
thread.setDaemon(true);
thread.start();
TimeUnit.MILLISECONDS.sleep(10);//确保线程已经启动
ThreadGroup mainGp = Thread.currentThread().getThreadGroup();
System.out.println("main组的活跃的线程数目:" + mainGp.activeCount());
System.out.println("main组的活跃的子group数目:" + mainGp.activeGroupCount());
System.out.println("main组的优先级:" + mainGp.getMaxPriority());
System.out.println("main组的父组" + mainGp.getParent());
System.out.println("----------------------------");
mainGp.list();
System.out.println("mainGp是不是gp的父组:" + mainGp.parentOf(gp));
}
控制台输出:
main组的活跃的子group数目:1
main组的优先级:10
main组的父组java.lang.ThreadGroup[name=system,maxpri=10]
----------------------------
java.lang.ThreadGroup[name=main,maxpri=10]
Thread[main,5,main]
java.lang.ThreadGroup[name=gp1,maxpri=10]
Thread[thread,5,gp1]
mainGp是不是gp的父组:true
这里需要注意一点:
1、我将thread线程设为守护线程,jvm检测到没有非守护线程,所以这里jvm会自动退出,若thread先启动在设为守护线程或者已经死亡在设为守护线程会抛出IllegalThreadStateException异常,同时可以看出守护线程具有自动结束生命周期的特点。
2、interrupt一个thread group会导致该group中所有的actie线程都被interrupt,详情请见源码。
ThreadGroup的destory:
destory用于销毁ThreadGroup,该方法只是针对没有任何一个active线程group进行一次标记,调用该方法的直接结果就是在父group中移除自身。(销毁ThreadGroup及其子ThreadGroup,得保证组下的线程必须是停止运行,如果有active线程存在则抛出IllegalThreadStateException)
public static void main(String[] args) {
ThreadGroup gp = new ThreadGroup("gp1");
Thread thread = new Thread(gp,() -> {
System.out.println("thread启动");
},"thread");
//thread.start();
ThreadGroup mainGp = Thread.currentThread().getThreadGroup();
mainGp.list();//将该组的所有活跃线程打印
gp.destroy();
System.out.println(gp.isDestroyed());
mainGp.list();
}
/* java.lang.ThreadGroup[name=main,maxpri=10]
Thread[main,5,main]
java.lang.ThreadGroup[name=gp1,maxpri=10]
true
java.lang.ThreadGroup[name=main,maxpri=10]
Thread[main,5,main]*/
守护ThreadGroup:
如果将一个group设置为daemon并不会影响线程的daemon,若一个线程组的被设置为守护线程组,那么组中没有任何active线程的时候该组将自动destory。
public static void mian(String[] args){
ThreadGroup gp1 = new ThreadGroup("GP1");
new Thread(gp1,() -> {
System.out.println("thread1");
},"thread1").start();
ThreadGroup gp2 = new ThreadGroup("GP2");
new Thread(gp2,() -> {
System.out.println("thread2");
},"thread2").start();
gp2.setDaemon(true);
TimeUnit.SECONDS.sleep(3);
System.out.println(gp1.isDestroyed());//fasle
System.out.println(gp2.isDestroyed());//true
}