一、简介
在之前的多线程系列文章中,我们陆陆续续的先容了Thread线程类相干的知识和用法,其着实Thread类上还有一层ThreadGroup类,也就是线程组。
本日我们就一起来简单的聊聊线程组相干的知识和用法。
二、什么是线程组
线程组,简单来说就是多个线程的聚集,它的出现重要是为了更方便的管理线程。
从结构角度看,线程组与线程之间其实是一个父子结构,一个线程组可以拥有几个线程,同时也可以拥有几个线程组。整个组织结构像一棵树一样,每个线程一定有一个线程组,线程组可能又有一个父线程组,追溯到根节点就是一个体系线程组。
线程组与线程之间的关系,可以用如下图来形貌。
比如,我们通常创建的main方法,对应的是main线程,它所属的是main线程组,main线程组的父级是是system体系线程组。- public static void main(String[] args) {
- Thread currentThread = Thread.currentThread();
- ThreadGroup currentThreadGroup = currentThread.getThreadGroup();
- ThreadGroup systemThreadGroup = currentThreadGroup.getParent();
- System.out.println("currentThread:" + currentThread.getName());
- System.out.println("currentThreadGroup:" + currentThreadGroup.getName());
- System.out.println("systemThreadGroup:" + systemThreadGroup.getName());
- }
复制代码 输出结果如下:- currentThread:main
- currentThreadGroup:main
- systemThreadGroup:system
复制代码 此中system线程组就是根节点,再上一层就没有了,如果调用会抛空指针异常。
线程组最重要的作用是:可以实现批量管理线程或者线程组,有效的对线程或者线程组对象举行检查、尝试中断等操作。
下面我们就一起来看看ThreadGroup的常用方法和使用技巧。
三、线程组用法详解
3.1、构造方法先容
ThreadGroup提供了两个构造方法,内容如下:
方法形貌ThreadGroup(String name)根据线程组名称创建线程组,其父线程组为main线程组ThreadGroup(ThreadGroup parent, String name)根据线程组名称创建线程组,其父线程组为指定的 parent 线程组此中支持指定父级线程组的方法,在现实的使用中比较常见。
下面,我们演示一下这两个构造函数的用法:- public static void main(String[] args) {
- ThreadGroup subThreadGroup1 = new ThreadGroup("sub1");
- ThreadGroup subThreadGroup2 = new ThreadGroup(subThreadGroup1, "sub2");
- System.out.println("sub1 parent thread group name:" + subThreadGroup1.getParent().getName());
- System.out.println("sub2 parent thread group name:" + subThreadGroup2.getParent().getName());
- }
复制代码 输出结果如下:- sub1 parent thread group name:main
- sub2 parent thread group name:sub1
复制代码 3.2、焦点方法先容
ThreadGroup提供了许多有效的方法,下面整理了一些方法的扼要先容,内容如下:
方法形貌public final String getName()返回此线程组的名称public final ThreadGroup getParent()返回此线程组的父级public final boolean parentOf(ThreadGroup g)测试此线程组是线程组参数还是其父级线程组之一public int activeCount()返回此线程组及其子组中运动线程的数量的估计值,递归遍历该线程组中所有的子组,此方法重要用于调试和监视目的public int activeGroupCount ()返回此线程组及其子组中运动组的数量的估计值。递归遍历该线程组中的所有子群,此方法重要用于调试和监视目的public final void checkAccess()确定当前运行的线程是否具有修改此线程组的权限public int enumerate(Thread[] list)将这个线程组复制到它所在的组及其子组中public final void destroy()烧毁此线程组及其所有子组,当线程组还要子线程或者子线程组,会抛异常public boolean isDestroyed()测试此线程组是否已被烧毁public final int getMaxPriority()返回此线程组的最大优先级public final void setMaxPriority(int pri)设置组的最大优先级。线程组中具有较高优先级的线程不会受到影响public final boolean isDaemon()测试此线程组是否是保卫线程组public final void setDaemon(boolean daemon)修改此线程组的保卫进程状态public final void interrupt()尝试中断此线程组中的所有线程public void list()将此线程组的信息打印到标准输出。此方法仅用于调试下面我们抽取几个比较常见的方法,举行演示先容。
3.2.1、activeCount 方法
activeCount()方法用于返回此线程组及其子组中运动线程的数量的估计值,因为线程的数量是动态发生变革的,返回的值只是一个估计值。
我们看一个简单的例子就知道了。- public class MyThread extends Thread{
- public MyThread(ThreadGroup group, String name) {
- super(group, name);
- }
- @Override
- public void run() {
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
复制代码- public class MyThreadMainTest {
- public static void main(String[] args) throws Exception {
- ThreadGroup tg = new ThreadGroup("group1");
- MyThread t1 = new MyThread (tg, "t1");
- MyThread t2 = new MyThread (tg, "t2");
- t1.start();
- t2.start();
- System.out.println("线程组的名称:" + tg.getName() + ",活动的线程数:" + tg.activeCount());
- Thread.sleep(1000);
- System.out.println("线程组的名称:" + tg.getName() + ",活动的线程数:" + tg.activeCount());
- }
- }
复制代码 输出结果如下:- 线程组的名称:group1,活动的线程数:2
- 线程组的名称:group1,活动的线程数:0
复制代码 第一次检查线程都处于运行状态,因此运动的线程数为 2;过 1 秒之后,线程运行结束,运动的线程数为 0。
3.2.2、isDaemon 方法
setDaemon()方法用于测试此线程组是否是保卫线程组。
需要注意的是:后台线程组和后台线程是两个概念,后台线程组的特性是末了一个线程实行完或末了一个线程被烧毁时,后台线程组主动烧毁,线程组只是为了同一管理线程的一个方式,跟后台线程有区别!
例子如下:- public class MyThread extends Thread{
- public MyThread(ThreadGroup group, String name) {
- super(group, name);
- }
- @Override
- public void run() {
- System.out.println("当前线程:" + Thread.currentThread().getName() + ",是否后台线程:" + Thread.currentThread().isDaemon());
- System.out.println("当前线程组:" + Thread.currentThread().getThreadGroup().getName() + ",是否后台线程组:" + Thread.currentThread().getThreadGroup().isDaemon());
- }
- }
复制代码- public class MyThreadMainTest4 {
- public static void main(String[] args) throws Exception {
- ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
- new MyThread(mainGroup, "t1").start();
- Thread.sleep(100);
- // 设置守护线程组
- ThreadGroup tg = new ThreadGroup("group1");
- tg.setDaemon(true);
- new MyThread(tg,"t2").start();
- }
- }
复制代码 输出结果如下:- 当前线程:t1,是否后台线程:false
- 当前线程组:main,是否后台线程组:false
- 当前线程:t2,是否后台线程:false
- 当前线程组:group1,是否后台线程组:true
复制代码 3.2.3、interrupt 方法
interrupt()方法用于尝试中断此线程组中的所有线程。如果正在运行的线程没有进入壅闭,是无法中断的。
例子如下:- public class MyThreadA extends Thread{
- public MyThreadA(ThreadGroup group, String name) {
- super(group, name);
- }
- @Override
- public void run() {
- System.out.println("线程:" + Thread.currentThread().getName() + ",开始运行");
- String t;
- for (int i = 0; i < 1000000000; i++) {
- t = i + "";
- }
- System.out.println("线程:" + Thread.currentThread().getName() + ",停止运行");
- }
- }
复制代码- public class MyThreadB extends Thread{
- public MyThreadB(ThreadGroup group, String name) {
- super(group, name);
- }
- @Override
- public void run() {
- System.out.println("线程:" + Thread.currentThread().getName() + ",开始运行");
- while (!Thread.interrupted()){
- }
- System.out.println("线程:" + Thread.currentThread().getName() + ",停止运行");
- }
- }
复制代码- public class MyThreadC extends Thread{
- public MyThreadC(ThreadGroup group, String name) {
- super(group, name);
- }
- @Override
- public void run() {
- System.out.println("线程:" + Thread.currentThread().getName() + ",开始运行");
- try {
- Thread.sleep(1000);
- } catch (Exception e){
- // e.printStackTrace();
- }
- System.out.println("线程:" + Thread.currentThread().getName() + ",停止运行");
- }
- }
复制代码- public class MyThreadMainTest {
- public static void main(String[] args) throws Exception {
- ThreadGroup tg = new ThreadGroup("group1");
- new MyThreadA(tg,"t1").start();
- new MyThreadB(tg,"t2").start();
- new MyThreadC(tg,"t3").start();
- // 尝试中断线程组里面的线程
- tg.interrupt();
- }
- }
复制代码 输出结果如下:- 线程:t1,开始运行
- 线程:t2,开始运行
- 线程:t2,停止运行
- 线程:t3,开始运行
- 线程:t3,停止运行
复制代码 线程t1只有等它运行结束,通过interrupt()不能中断步伐!
四、小结
本文重要围绕线程组的一些根本概念以及常用方法,并联合了一些简单示例举行先容。
线程组的出现更多的是便于有组织的管理线程,比如 Java 的线程池就用到了线程组,更多的线程知识,我们在后续的文章中会举行先容。
如果有形貌不对的地方,欢迎网友留言指出。
五、参考
1、https://www.cnblogs.com/xrq730/p/4856072.html
2、https://cloud.tencent.com/developer/article/1633465
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |