深入浅出Java多线程(十)之ThreadGroup详解(上)

606 阅读3分钟

这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战

前言

ThreadGroup → 为线程服务,用户通过使用线程组的概念批量管理线程,如批量停止或挂起等。

1.Thread 和 ThreadGroup

在Java程序中,默认的情况下新的 Thread 都会默认添加进 main 线程所在的 group 中,main线程的group与线程同名。如同父子线程一样,ThreadGroup 也存在父子关系。
无论如何,线程都会被加入某个ThreadGroup之中。

2.创建 ThreadGroup

  • public ThreadGroup (String name);
  • public ThreadGroup (ThreadGroup parent , String name);

创建ThreadGroup的语法非常简单,第一个构造方法为ThreadGroup赋予了名字,该ThreadGroup的父类为创建该线程组的线程的ThreadGroup;
第二个构造方法显示指定了父级的ThreadGroup,并赋予自身名字。

    public static void main(String[] args) {
        //新建一个线程组,赋予名字,父级线程组默认当前线程的线程组。
        ThreadGroup threadGroup = new ThreadGroup("我是子级线程组");
        //true
        System.out.println(Thread.currentThread().getThreadGroup() == threadGroup.getParent());
        //创建线程组,赋予名字+指定父级线程组
        ThreadGroup threadGroup1 = new ThreadGroup(threadGroup,"超级子级");
        //true
        System.out.println(threadGroup1.getParent() == threadGroup);
    }

3.复制Thread数组和ThreadGroup数组

复制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[] list , true)

注意

  • enumerate方法获取的线程仅仅是个预估值,并不能百分之百地保证当前group的活跃线程,比如在调用复制之后,某个线程结束了生命周期或者新的线程加入了进来,都会导致数据的不准确。
  • enumerate方法的返回值int相比较Thread[] 的长度更为真实,比如定义了数组长度的Thread数组,那么 enumerate方法仅仅会将当前活跃的thread分别放进数组中,而返回值int则代表真实的数量,并非数组的长度

复制 ThreadGroup 数组

  • public int enumerate(ThreadGroup[] list)
  • public int enumerate(ThreadGroup[] list, boolean recurse)

和复制Thread数组类似,上述方法,主要用于复制当前的ThreadGroup的子Group,同样recurse会决定是否以递归方式复制。

    public static void main(String[] args) throws InterruptedException {
        ThreadGroup myGroup1 = new ThreadGroup("MyGroup1");
        ThreadGroup myGroup2 = new ThreadGroup(myGroup1,"MyGroup2");
        TimeUnit.SECONDS.sleep(2);
        ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
        ThreadGroup[] list = new ThreadGroup[mainGroup.activeCount()];
        int recurseSize = mainGroup.enumerate(list);
        System.out.println(recurseSize);
        recurseSize = mainGroup.enumerate(list,false);
        System.out.println(recurseSize);

    }

总结

线程组:
可以批量管理线程或线程组对象,有效地对线程或线程组对象进行组织。用户创建的所有线程都属于指定线程组,如果没有显示指定属于哪个线 程组,那么该线程就属于默认线程组(即main线程组)。默认情况下,子线程和父线程处于同一个线程组。只有在创建线程时才能指定其所在的线 程组,线程运行中途不能改变它所属的线程组,也就是说线程一旦指定所在的线程组,就直到该线程结束。