六、【Java 并发】ThreadGroup 详解

ThreadGroup 与 Thread

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

image.png

创建 ThreadGroup

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

  • public ThreadGroup(String name)
  • public ThreadGroup(ThreadGroup parent, String name)
public static void main(String[] args) {

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


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

}

复制 Thread

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

两个方法,都可以讲 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 数组

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

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

ThreadGroup 操作

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

  • activeCount() 用于获取 group 中活跃的线程,这只是个估计值,并不能百分之百的保证正确。
  • activeGroupCount() 获取 group 中活跃的子 group,这也是一个估值,方法方法会递归获取所有子 group。
  • getMaxPriority() 用于获取 group 的优先级,默认情况下,Group 的优先级为 10,在group 中,所有线程的优先级都不能大于 group 的优先级
  • getName() 获取 group 的名字
  • getParent() 用于获取 group 的父 group,如果父 group 不存在,则会返回 null,比如 system group 的父 group 就为 null。
  • list() 该方法没有返回值,调用该方法会将 group 中所有的活跃线程信息全部输出到控制台,也就是 System.out
  • parentOf(ThreadGroup g) 会判当前 group 是不是传入 group 的父 group。如果传入的 group 就是自己本身,该方法也回返回 true。
  • setMaxPriority(int pri) 指定 group 的最大优先级,最大优先级不能超过父 group 的最大优先级,执行该方法不仅会改变当前 group 的最大优先级,还会改变所有子 group 的最大优先级

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。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,820评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,648评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,324评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,714评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,724评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,328评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,897评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,804评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,345评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,431评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,561评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,238评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,928评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,417评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,528评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,983评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,573评论 2 359

推荐阅读更多精彩内容