线程组,顾名思义,就是线程的组,逻辑相似项目组,用于管理项目成员,线程组就是用来管理线程。
每一个线程都会有一个线程组,若是没有设置将会有些默认的初始化设置
而在java中线程组则是使用类ThreadGroup 进行抽象描述
既然线程组是用来管理线程的,天然更多的是一种管理维度的抽象,因此不少方法也都是这个理念
构造方法
想要了解一个类的具体信息,第一个要看的就是构造方法,看一下最多的内容的那个构造方法就能够大体了解到有哪些属性了
ThreadGroup有两个构造方法
仔细看下这两个构造方法,其实只有一个了,那就是底层的私有的这一个
对于一个线程组来讲,他拥有他本身的名字,也拥有他的优先级,也有是不是守护的说法
不一样于线程,对于线程组来讲,他是有记录本身的父线程组的,经过parent
另外,线程组也记录了本身下面有哪些线程组,使用数组记录,也就是构造方法中的 parent.add(this)
因此一个线程组核心的信息是:名称、优先级、是否守护、父线程组、子线程组
另外还有一个默认的构造方法,看注释,用来建立系统线程组
名称
线程组的名称借助于内部的name属性持有
经过构造方法能够设置名称
提供了get方法用于获取名称
优先级
此处的优先级,表示的是最大容许优先级,线程组内最大就容许这么大
里面全部的线程不能继续变大,不要认为是记录了里面全部的线程中最大的那个值,是一个天花板,不是一个记录尺
daemon
父线程组
对于线程组来讲,是明确的记录了他的父
借助于parent这个属性值,能够获取一个线程组的父线程组,也能够用来肯定是不是一个指定线程组的父或者祖先
子线程组
内部借助于ThreadGroup 数组维护内部的线程组,从这个数据组织结构来看,就很显然,线程组内能够有线程组,能够层层嵌套造成树状结构的
对于线程组的建立,他必然会有一个父线程组(不设置就是当前线程所在的线程组了,也能够简单说当前线程组)
建立线程组的时候,就会借助于add方法,将这个线程组加入到父线程组维护的数组内
对于任何一个线程,也都是拥有一个线程组,若是没有设置,将会将当前线程的线程组做为线程组,这个在前面已经说过
而在start方法中,又将当前线程添加到了线程组,请看下面的源码截图
在回头看下这个add方法,借助于内部的线程数组,其实就是将这个线程添加到数组内
- nThreads 记录的就是线程组内部的线程个数
- nUnstartedThreads记录的是未启动的个数
刚刚调用线程的start方法,这个数就要减1,尽管可能这个瞬间线程可能并无真正的启动,确保可以明确的声明线程组内有启动的线程了
因此就由这几项数据组成了线程组的树形结构
也就是说
- 每一个线程组也都知道本身包含多少个线程,哪些线程;
- 每一个线程组也都知道本身包含了多少个线程组,哪些线程组;
这是一份很重要的信息,借助于这些信息就彻底串联起来了
子线程组相关方法
既然是树形结构,那么天然可能有枚举节点的需求
ThreadGroup中提供了两类enumerate方法,看名字应该就能够理解含义了,用于枚举线程和线程组
线程枚举
底层依赖于私有枚举方法,把此线程组及其子组中的全部活动线程复制到指定数组中。能够设置是否递归枚举
两个方法中,若是不指定是否递归,那么默认是递归的,他们都将参数数组的第一个元素开始写入(0号下标)
很显然,他们内部就是借助于树结构的变量,nThreads和thread[]数组
须要注意的是,若是数组内空间不足,多余的线程将不可以保存进去,并且保存的是alive状态的
activeCount
该线程组以及子线程组中,活动线程的估计数。注意是一个估计数,估计数,估计数
activeGroupCount
相似activeCount,这个方法是返回的线程组的个数,仍旧是估计数,估计数,估计数
list方法
list看注释,用于调试,底层依赖方法list(PrintStream out, int indent),indent表示的是缩进,也就是空格个数
仍旧是借助于nthreads和ngroups以及threads数组和group数组,也就是树形结构循环遍历打印信息
interrupt()方法
中断此线程组中的全部线程,能够看得出来:
仍旧是遍历树形结构,核心是调用全部线程的interrupt方法
因此,此方法是中断该线程组以及全部子线程组中的全部线程
线程组的销毁
线程组的销毁内部借助于boolean变量 destroyed 进行标识
getter方法,isDestroyed直接返回此字段
而setter方法destroy,也是设置这个字段,可是还有一些逻辑判断与处理
destroy()负责销毁此线程组及其全部子组。
- 会进行权限校验
- 而且此线程组必须为空,也就是nthreads > 0不成立,也就是此线程组中的全部线程都已中止执行。
- 而且会将子线程组中的也进行销毁,是递归进行的,显然,若是子线程组中线程非空,那么仍旧会抛出异常
权限校验checkAccess
checkAccess就是总提到的一个借助于安全管理器进行权限校验的封装
肯定当前运行的线程是否有权修改此线程组
异常处理器
uncaughtException,是用于异常处理的设置,此处不讲,后续单独章节。
总结
从前面的描述能够看得出来,线程组就是对线程进行管理的一个抽象构建,他包括了自身的一些信息,还有一大部分就是对于线程的管理
线程组中有线程,也有线程组,借助于两个变量和两个数组完成了树形结构的构造,不少方法都是借助于这个树形结构完成的,好比枚举
想要理解线程组,就要理解线程组“管理”角色的内涵,而且对线程组的树形结构了解
既然是管理线程,因此线程中的一些功能或者属性也是依赖线程组的,好比优先级,线程不能超过线程组的最大优先级,再好比Thread中的activeCount(),实际上就是currentThread().getThreadGroup().activeCount();
总之,必定要理解管理二字的含义