六、【Java 并发】ThreadGroup 详解

2021-08-24  本文已影响0人  deve_雨轩

ThreadGroup 与 Thread

默认情况下,新的线程都会加入到创建它的线程(也就是父线程)所在的 group 中。如同线程存在父子关系一样,ThreadGroup 同样也存在父子关系。

image.png

创建 ThreadGroup

创建 ThreadGroup 非常简单,可通过两个构造函数来创建。

public static void main(String[] args) {

    //指定名称不指定父线程组  (默认父线程组为创建线程组的线程的线程组,也就是当前线程的父线程组)
    ThreadGroup myGroup = new ThreadGroup("myGroup");


    //指定名称  指定父线程组
    ThreadGroup myGroup2 = new ThreadGroup(myGroup, "myGroup2");

}

复制 Thread

两个方法,都可以讲 Thread 中的 active 线程全部复制到 Thread 数组中,其中 recurse 参数如果为 true,则会将所有的自 group 中的 active 线程都递归到 Thread 数组中,enumerate(Thread list[])等价于enumerate(Thread list[], true),如果为 false,只会复制调用此方法的线程组中的 active 线程,其子线程组中的 active 线程不会复制

 public static void main(String[] args) {

        //指定名称不指定父线程组  (默认父线程组为创建线程组的线程的线程组,也就是当前线程的父线程组)
        ThreadGroup myGroup = new ThreadGroup("myGroup");
        Thread thread3 = new Thread(myGroup,new Runnable() {
            @Override
            public void run() {
                while(true){
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        thread3.start();


        //指定名称  指定父线程组
        ThreadGroup myGroup2 = new ThreadGroup(myGroup, "myGroup2");

        Thread thread = new Thread(myGroup2,new Runnable() {
            @Override
            public void run() {
                while(true){
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        Thread thread1 = new Thread(myGroup2,new Runnable() {
            @Override
            public void run() {
                while(true){
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        thread.start();
        thread1.start();

        System.out.println("activecount: "+myGroup.activeCount());
        //myGroup.activeCount() 获取线程组中的 active 线程数,包括子线程组中的
        Thread[] t = new Thread[myGroup.activeCount()];
//        int size = myGroup.enumerate(t,true);
        int size = myGroup.enumerate(t,false);
        System.out.println("size: "+size);
    }

enumerate 方法获取的线程仅仅是个预估值,并不能百分之百地保证当前 group 的活跃线程,比如在调用复制之后,某个线程结束了声明周期或者新的线程加入了进来,都会导致数据不准确。
enumerate 方法返回值是本次复制,active 线程真实的数量。

复制 ThreadGroup 数组

和复制 Thread 数组类似,上面两个方法主要用于复制当前 ThreadGroup 的子 Group,同样 recurse 会决定是否复制子 Group 中的子 Group。

ThreadGroup 操作

ThreadGroup 并不能提供对线程的管理,ThreadGroup 的主要功能是对线程进行组织。

ThreadGroup 的 interrupt

interrupt 一个 ThreadGroup 会导致该 group 中所有的 active 线程都被 interrupt,也就是说该 group 中所有子线程的 interrupt 标识都被设置了。

ThreadGroup 的 destroy

destroy 用于销毁 ThreadGroup,该方法只是针对一个没有任何 active 线程的 group 进行一次 destroy 标记,调用该方法的直接结果是在父 group 中将自己移除,调用 destroy 方法的前提是该 ThreadGroup 中所有的线程必须是空的,也就是说所有线程包括子 group 中所有线程都已经停止运行,如果有 active 线程存在,调用 destroy 方法则会抛出异常。

守护 ThreadGroup

线程可以设置为守护线程,ThreadGroup 也可以设置为守护 ThreadGroup,但是将一个 ThreadGroup 设置为 daemon,并不会影响线程的 daemon 属性,如果一个 ThreadGroup 被设置为守护,那么在该 group 中没有任何 active 线程的时候该 group 将自动 destroy。

上一篇 下一篇

猜你喜欢

热点阅读