美文网首页
并发系列之ThreadGroup

并发系列之ThreadGroup

作者: 阿伦故事2019 | 来源:发表于2019-07-28 13:51 被阅读0次

    首尔国立大学(韩国)校训:“真理是我的光明。”


    生活的前方不管有多少荆棘,我都随身携带着镰刀,砥砺前行;烈日高阳,打一罐鸡血,开启一天的新生活!
    前面几篇聊了很多线程的基础知识,今天讲下线程的家族式管理ThreadGroup,类似中国的宗族制,每个人都有隶属的一脉,绝不可能是游离的;同样,jvm管理线程也采用了这种思想,每个线程也绝不会是游离的,都有隶属的ThreadGroup。可能大家在工作中没有注意到它的存在,但在某些场景下还是很有用途的。下面就从线程组的基本概念/管理结构/使用场景简单聊下:

    一 概述线程组

    线程组管理线程是一种组织式地管理,类似与公司的组织架构管理,要注意与线程池管理线程进行区分;它是按一定层级结构管理线程或线程组对象,线程和线程组构成的结构是树形,可以通过递归遍历的方式获取整个线程树。线程组有几个重要特性,如下:
    1/自动归属,即线程或线程组具有默认机制,通俗地说,创建一个线程或线程组,它必有自己的所属的线程组,每个线程都不可能是游离的,这可以通过查看new Thread()和new ThreadGroup()的源码查阅便知。
    2/多级关联,父对象中有子对象,子对象可创建子对象,子子孙孙无穷尽也,这是基于jdk提供的线程树结构,但在实际开发中,都是以简单易读地方式管理线程,所以推荐一级关联。
    3/一级关联,父对象中有子对象,但不能创建孙对象,即树形结构只有两层,这在实际工作中大部分场景已经够用,组织结构越简单,自然管理也就越简单,故在工作中推荐使用。
    demo世界不孤单,请阅:

    /**
     * @author 阿伦故事
     * @Description:描述线程组的基本属性
     * */
    @Slf4j
    public class GroupBasic {
    
        public static void main(String[] args) {
            GroupBasic groupBasic = new GroupBasic();
            //auto
            groupBasic.auto();
            //one level
            groupBasic.oneLevel();
            //multi level
            groupBasic.multiLevel();
        }
        /**
         * 自动归属
         * */
        public void auto(){
            Thread current = Thread.currentThread();
            Thread thread = new Thread(()->{
                log.info("---run---");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            thread.start();
            log.info("--current thread name:"+current.getName() + ",线程组:"+current.getThreadGroup().getName());
            log.info("--new thread name:"+thread.getName() + ",线程组:"+thread.getThreadGroup().getName());
        }
        /**
         * 一级关联
         * */
        public void oneLevel(){
            ThreadGroup group = new ThreadGroup("一级线程组");
            Thread t1 = new Thread(()->{
                log.info("---t1 run---");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            Thread t2 = new Thread(()->{
                log.info("---t2 run---");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            Thread one = new Thread(group, t1);
            Thread two = new Thread(group, t2);
            one.start();
            two.start();
            log.info("--ThreadGroup name:"+group.getName() + ",存活线程个数:"+group.activeCount());
        }
        /**
         * 多级关联
         * */
        public void multiLevel(){
            ThreadGroup group = new ThreadGroup("一级线程组");
            ThreadGroup group1 = new ThreadGroup(group,"二级线程组A");
            ThreadGroup group2 = new ThreadGroup(group,"二级线程组B");
            Thread t1 = new Thread(()->{
                log.info("---t1 run---");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            Thread t2 = new Thread(()->{
                log.info("---t2 run---");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            Thread t3 = new Thread(()->{
                log.info("---t3 run---");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            Thread one = new Thread(group, t1);
            Thread two = new Thread(group1, t2);
            Thread three = new Thread(group2, t3);
            one.start();
            two.start();
            three.start();
            log.info("--一级线程组 name:"+group.getName() + ",存活线程个数:"+group.activeCount()
                    +",子线程组个数:"+group.activeGroupCount());
            log.info("--二级线程组A name:"+group1.getName() + ",存活线程个数:"+group1.activeCount()
                    +",子线程组个数:"+group1.activeGroupCount());
            log.info("--二级线程组B name:"+group2.getName() + ",存活线程个数:"+group2.activeCount()
                    +",子线程组个数:"+group2.activeGroupCount());
        }
    }
    

    二 线程批管理

    线程组在实战中有什么用呢,主要用对一批线程进行管理,如中断(interrupt)/暂停(suspend)/恢复(resume)/终止(stop)等操作,这里注意下ThreadGroup的destroy方法,是清除掉这个线程组及其所有子线程组,但要注意这里的所有线程组包括子线程组必须是空的,也就是说线程组里的线程都销亡了,否则会抛出异常。
    这里主要讲下实战中的使用场景:
    1/在单个应用中,使用多线程开发,必然声明线程池管理线程,建议根据业务模块声明相应的线程组来管理,便于针对某一业务模块的线程做统一处理;
    2/在任务调度模块中,声明多个耗时任务执行数据处理,如果定时任务长时间未执行完毕,可能是由于执行过程中出现了异常等,这时需要把这类任务终止,就可以利用线程组把一类线程中断掉。
    demo世界不孤单,请阅:

    /**
     * @author 阿伦故事
     * @Description:描述线程组批处理
     * */
    @Slf4j
    public class GroupBatch {
        public static void main(String[] args) throws InterruptedException{
            GroupBatch groupBatch = new GroupBatch();
            groupBatch.batchTest();
        }
        /**
         * 线程组下的线程任务执行异常,需要全部终止
         * */
        public void batchTest() throws InterruptedException{
            ThreadGroup group = new ThreadGroup("批处理线程组");
            for (int i = 0; i <5 ; i++) {
                new Thread(group, new SubTask(),"subtask-0"+i).start();
            }
            Thread.sleep(5000);
            log.info("--all SubTask 阻塞,需终止--");
            group.interrupt();//中断线程组下的所有线程任务
            Thread.sleep(2000);
            log.info("--stop the world--");
        }
        static class SubTask implements Runnable{
            @Override
            public void run() {
                log.info("--subTask thread name:"+ Thread.currentThread().getName() + ",begin run");
                while(!Thread.currentThread().isInterrupted()){ };
                log.info("--subTask thread name:"+ Thread.currentThread().getName() + ",end run");
            }
        }
    }
    

    特此声明:
    分享文章有完整的知识架构图,将从以下几个方面系统展开:
    1 基础(Linux/Spring boot/并发)
    2 性能调优(jvm/tomcat/mysql)
    3 高并发分布式
    4 微服务体系
    如果您觉得文章不错,请关注阿伦故事,您的支持是我坚持的莫大动力,在此受小弟一拜!


    每篇福利:

    评论区打出车型.jpg

    相关文章

      网友评论

          本文标题:并发系列之ThreadGroup

          本文链接:https://www.haomeiwen.com/subject/tomurctx.html