拾遗增补(二)——线程组

news2024/9/25 3:18:54

目录

  • 1.线程关联线程组:1级关联
  • 2.线程对象关联线程组:多级关联
  • 3.线程组自动归属特性
  • 4.获取根线程组
  • 5.线程组里加线程组
  • 6.组内的线程的批量停止
  • 7.递归与非递归取得组内对象

  可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的组织结构有点类似于树的形式,如图所示:
在这里插入图片描述
  线程组的作用是:可以批量管理线程或线程组对象,有效地对线程或线程组对象进行组织。

1.线程关联线程组:1级关联

  所谓1级关联就是父对象中有子对象,但并不创建子孙对象。这种情况经常出现在开发中,比如创建一些线程时,为了有效对这些线程进行阻止管理,通常情况下是创建一个线程组,然后再将部分线程归属到该组中。这样的处理可以对零散的线程对象进行有效的组织与规划。
  创建名称为7.2.1的项目。
  创建两个线程类,如下
类ThreadA.java代码如下:

public class ThreadA extends Thread {
    @Override
    public void run() {
        super.run();
        try {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("Thread name : " + Thread.currentThread().getName());
                Thread.sleep(3000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

类ThreadB.java代码如下:

public class ThreadB extends Thread {
    @Override
    public void run() {
        super.run();
        try {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("Thread name : " + Thread.currentThread().getName());
                Thread.sleep(3000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

创建运行类Run.java代码如下:

public class Run {
    public static void main(String[] args) {
        ThreadA aRunnable = new ThreadA();
        ThreadB bRunnable = new ThreadB();
        ThreadGroup group = new ThreadGroup("线程组");
        Thread aThread = new Thread(group, aRunnable);
        Thread bThread = new Thread(group, bRunnable);
        aThread.start();
        bThread.start();
        System.out.println("活动的线程数 : " + group.activeCount());
        System.out.println("线程组的名称 : " + group.getName());
    }
}

程序运行后的结果如下所示:

活动的线程数 : 2
Thread name : Thread-2
Thread name : Thread-3
线程组的名称 : 线程组
Thread name : Thread-2
Thread name : Thread-3
Thread name : Thread-2
Thread name : Thread-3
Thread name : Thread-2
Thread name : Thread-3
Thread name : Thread-2
Thread name : Thread-3

  控制台中打印的信息表示线程组中有两个线程,并且打印出了线程组的名称。另外,两个线程一直无限地并且每隔3秒打印日志。

2.线程对象关联线程组:多级关联

  所谓的多级关联就是父对象中有子对象,子对象中再创建子对象,也就出现了子孙的效果了。但是这种写法在开发中不太常见,因为线程树如果涉及得复杂反而不利于线程对象的管理,不过JDK确实提供了多级关联的线程树结构。
  创建名称为7.2.2的项目。
  创建运行类Run.java代码如下:

public class Run {
    public static void main(String[] args) {
        //再main组中添加一个线程组A,然后在这个A组中添加线程对象Z
        //方法acativeGroupCount()和activeCount()的值不是固定的
        //是系统中环境的一个快照
        ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
        ThreadGroup group = new ThreadGroup(mainGroup, "A");
        Runnable runnable = new Runnable() {

            @Override
            public void run() {
                try {
                    System.out.println("run method");
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        Thread newThread = new Thread(group, runnable);
        newThread.setName("Z");
        newThread.start();//线程必须启动然后才归到A中
        ThreadGroup[] listGroup = new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];
        Thread.currentThread().getThreadGroup().enumerate(listGroup);
        System.out.println("main线程中有多少个线程组:" + listGroup.length + "个子线程,名字:" + listGroup[0].getName());
        Thread[] listThread = new Thread[listGroup[0].activeCount()];
        listGroup[0].enumerate(listThread);
        System.out.println(listThread[0].getName());
    }
}

  程序运行结果如下所示。

main线程中有多少个线程组:1个子线程,名字:A
run method
Z

运行结果

  本程序代码的结构就是main组创建一个新组,然后又在该新组中添加了线程。

3.线程组自动归属特性

  自动归属就是自动归到当前线程组中。
  创建名称为7.2.3项目。
  创建运行类Run.java代码如下:

public class Run {
    public static void main(String[] args)
    {
        System.out.println("A处线程:" + Thread.currentThread().getName() + ", 所属线程:" + Thread.currentThread().getThreadGroup().getName() +
                ", 组中有线程组数量:" + Thread.currentThread().getThreadGroup().activeGroupCount());
        ThreadGroup group = new ThreadGroup("新的组");
        System.out.println("B处线程:" + Thread.currentThread().getName() + ", 所属线程:" + Thread.currentThread().getThreadGroup().getName() +
                ", 组中有线程组数量:" + Thread.currentThread().getThreadGroup().activeGroupCount());
        ThreadGroup[] tg = new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];
        Thread.currentThread().getThreadGroup().enumerate(tg);
        for (int i = 0; i < tg.length; i++)
            System.out.println("第一个线程组名称为:" + tg[i].getName());
    }
}

  程序运行后的结果如下所示:

A处线程:main, 所属线程:main, 组中有线程组数量:0
B处线程:main, 所属线程:main, 组中有线程组数量:1
第一个线程组名称为:新的组

  本实验要证明的是,在实例化一个ThreadGroup线程组x时如果不指定所属的线程组,则x线程组自动归到当前线程对象所属的线程组中,也就是隐式地在一个线程组中添加了一个子线程组,所以在控制台中打印的线程组数量值由0变成了1。

4.获取根线程组

  创建名称为7.2.4项目。
  创建运行类Run.java代码如下:

public class Run {
    public static void main(String[] args)
    {
        System.out.println("线程:" + Thread.currentThread().getName() + "所在的线程组名为:"
        + Thread.currentThread().getThreadGroup().getName());
        System.out.println("main线程所在的线程组的父线程组的名称是:" +
                Thread.currentThread().getThreadGroup().getParent().getName());
        System.out.println("main线程所在的线程组的父线程组的父线程组的名称是:" +
                Thread.currentThread().getThreadGroup().getParent().getParent().getName());
    }
}

  程序运行后的结果如下所示:

线程:main所在的线程组名为:main
main线程所在的线程组的父线程组的名称是:system
Exception in thread "main" java.lang.NullPointerException
	at Run.main(Run.java:9)

  运行结果说明JVM 的根线程组就是 system,再取其父线程组则出现空异常。

5.线程组里加线程组

  创建名称为7.2.5项目。
  创建运行类Run.java代码如下:

public class Run {
    public static void main(String[] args) {
    System.out.println("线程组名称:"
            + Thread.currentThread().getThreadGroup().getName());
    System.out.println("线程组中活动的线程数量:"
            + Thread.currentThread().getThreadGroup().activeCount());
    System.out.println("线程组中线程组的数量-加之前:"
            + Thread.currentThread().getThreadGroup().activeGroupCount());
    new ThreadGroup(Thread.currentThread().getThreadGroup(), "newGroup");
    System.out.println("线程组中线程组数量-加之后:"
            + Thread.currentThread().getThreadGroup().activeGroupCount());
    System.out.println("父线程组名称:"
            + Thread.currentThread().getThreadGroup().getParent().getName());
}
}

  程序运行后的结果如下所示:

线程组名称:main
线程组中活动的线程数量:2
线程组中线程组的数量-加之前:0
线程组中线程组数量-加之后:1
父线程组名称:system

  本实验用显式的方式在一个线程组中添加了一个线程组。

6.组内的线程的批量停止

  创建名称为7.2.6项目。
  创建MyThread.java类代码如下:

public class MyThread extends Thread{
    public MyThread(ThreadGroup group, String name){
        super(group, name);
    }
    @Override
    public void run() {
        System.out.println("ThreadName=" + Thread.currentThread()
                .getName() + "准备开始死循环了:)");
        while (!this.isInterrupted()) {
        }
        System.out.println("ThreadName=" + Thread.currentThread().getName()
                +"结束了:)");
    }
}

  创建运行类Run.java代码如下:

public class Run {
    public static void main(String[] args) {
        try {
            ThreadGroup group = new ThreadGroup("我的线程组");
            for (int i = 0; i < 5; i++) {
                MyThread thread = new MyThread(group, "线程" + (i + 1));
                thread.start();
            }
            Thread.sleep(5000);
            group.interrupt();
            System.out.println("调用了interrupt()方法");
        } catch (InterruptedException e) {
            System.out.println("停了!");
            e.printStackTrace();
        }
    }
}

  程序运行后的结果如下所示:

ThreadName=线程2准备开始死循环了:)
ThreadName=线程1准备开始死循环了:)
ThreadName=线程5准备开始死循环了:)
ThreadName=线程3准备开始死循环了:)
ThreadName=线程4准备开始死循环了:)
调用了interrupt()方法
ThreadName=线程2结束了:)
ThreadName=线程3结束了:)
ThreadName=线程4结束了:)
ThreadName=线程5结束了:)
ThreadName=线程1结束了:)

  通过将线程归属到线程组中,当调用线程组 ThreadGroup 的 interrupted() 方法时,可以将该组中的所有正在运行的线程批量停止。

7.递归与非递归取得组内对象

  创建名称为7.2.7项目。
  创建运行类Run.java代码如下:

public class Run {
    public static void main(String[] args) {
        ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
        ThreadGroup groupA = new ThreadGroup(mainGroup, "A");
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("runMethod!");
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        ThreadGroup groupB = new ThreadGroup(groupA, "B");
        //分配空间,但不一定全部用完
        ThreadGroup[] listGroup1 = new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];
        //传入true是递归取得子组及子孙组
        Thread.currentThread().getThreadGroup().enumerate(listGroup1,true);
        for (int i = 0; i < listGroup1.length; i++) {
            if (null != listGroup1[i]) {
                System.out.println(listGroup1[i].getName());
            }
        }
        ThreadGroup[] listGroup2 = new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];
        //传入true是递归取得子组及子孙组
        Thread.currentThread().getThreadGroup().enumerate(listGroup2,false);
        for (int i = 0; i < listGroup2.length; i++) {
            if (null != listGroup2[i]) {
                System.out.println(listGroup2[i].getName());
            }
        }
    }
}

  程序运行后的结果如下所示:

A
B
A


以上代码下载请点击该链接:https://github.com/Yarrow052/Java-package.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/127650.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

58.Python的递归函数

58.Python的递归函数 文章目录58.Python的递归函数1.递归的形象解释2.定义3.步骤4.终止条件5.优点6.缺点7.调用深度8.课堂实例9.计算n的阶乘9.1什么是阶乘9.2计算5&#xff01;1.递归的形象解释 我们首先看一段视频&#xff0c;来形象理解什么是递归。 视频作者&#xff1a;p…

完整的OpenDDS的发布订阅编写及源码(Windows)

一个完整的OpenDDS的发布订阅编写及源码,包括SimuMsg.idl、SimuMsg.mwc和SimuMsg.mpc,SimuMsgCommon_Export.h、publisher.cpp、subscriber.cpp、SimuMsgDataReaderListenerImpl.h和SimuMsgDataReaderListenerImpl.cpp、SimuMsgDataWriterListenerImpl.h和SimuMsgDataWriterL…

还有企业没有在用它嘛! 适配于多行业的管理系统,各企业之首选

在信息技术高速发展的现代社会&#xff0c;世界经济一体化和企业经营全球化已成为大势所趋。在此背景下&#xff0c;企业为增强自身的竞争力&#xff0c;就要强化管理&#xff0c;规范业务流程&#xff0c;提高透明度&#xff0c;加快商品资金周转&#xff0c;以及为流通领域信…

使用MariaDB线程池提高MySQL的扩展性

摘要&#xff1a;MySQL的线程池能够有效地解决大量短连接的性能问题&#xff0c;大幅提高MySQL数据库的扩展性。但官方MySQL的线程池在收费的企业版中才有&#xff0c;免费的社区版中没有这个功能&#xff0c;这里介绍MairaDB的线程池。 关于作者&#xff0c;姚远&#xff1a;…

不用梯子,GitHub也能访问并提速

引言 我们都知道国内访问github会非常慢&#xff0c;甚至打不开&#xff0c;具体原因这里就不聊了~我们这里聊怎么不用梯子&#xff0c;GitHub也能访问并提速&#xff01; Github打开慢的原因 Github打开慢的原因其中一个原因&#xff1a;GitHub的CDN域名遭到DNS污染&#xf…

好用的开源个人博客推荐

原文网址&#xff1a;好用的开源个人博客推荐_IT利刃出鞘的博客-CSDN博客 简介 本文推荐个人从几十款开源个人博客中精选的几款开源博客。 halo Github 地址 &#xff1a;https://github.com/halo-dev/halo Star : 24.3k 简介 &#xff1a;一个优秀的开源博客应用。 技术 …

java学习day66(乐友商城)搜索过滤

1.过滤功能分析 首先看下页面要实现的效果&#xff1a; 整个过滤部分有3块&#xff1a; 顶部的导航&#xff0c;已经选择的过滤条件展示&#xff1a; 商品分类面包屑&#xff0c;根据用户选择的商品分类变化 其它已选择过滤参数 过滤条件展示&#xff0c;又包含3部分 商品分…

CNN神经网络

CNN神经网络0.引言0.1.卷积0.2.Relu函数0.3.池化pooling0.4.小节1.前向传播1.1.input layer --> convolution layer1.2.Hidden Layer --> convolution layer1.3.Hidden layer --> pooling layer1.4.Hidden layer --> full connected layer1.5.小节2.反向传播2.1.po…

如何实现微信和淘宝的扫码登录

1、引言 扫码登录这个功能&#xff0c;最早应该是微信的PC端开始搞&#xff0c;虽然有点反人类的功能&#xff08;不扫码也没别的方式登录&#xff09;&#xff0c;但不得不说还是很酷的。 下面这张图&#xff0c;不管是IM开发者还是普通用户&#xff0c;应该很熟悉&#xff…

高德地图WebGIS

GIS:地理信息系统 1 Web前端JSAPI X.1 创建app ​​​​ X.2 地图显示

热榜,Alibaba最新发布SprinBoot:进阶原理实战与面试题分析指南

为什么要写这本书&#xff1f; 我们知道&#xff0c;Spring Boot是一个集成性的开源框架&#xff0c;内部整合了很多第三方组件和框架。这些组件和框架应用如此之广泛&#xff0c;以至于大家反而往往对如何更好地使用Spring Boot自身的功能特性并不是很重视。事实上&#xff0…

自动化会计从这四个流程开始

自动化会计从这四个流程开始 会计和财务业务流程的自动化对企业领导者来说是一个巨大的机会。对于首席财务官 &#xff08;CFO&#xff09; 而言&#xff0c;可以让他们在改善运营和降低成本等传统角色中脱颖而出&#xff0c;同时利用他们在自动化方面的经验成为整个公司数字业…

SpringBoot 单元测试利器-Mockito

Mockito 是一种 Java mock 框架&#xff0c;他主要是用来做 mock 测试的&#xff0c;他可以模拟任何 Spring 管理的 bean、模拟方法的返回值、模拟抛出异常...等&#xff0c;在了解 Mockito 的具体用法之前&#xff0c;得先了解什麽是 mock 测试 1. 什么是 mock 测试&#xff…

Java Long对象对比,用equals函数

文章目录一、前文二、调试三、后记一、前文 同事问我一个问题&#xff0c;我咋一看也愣住了 代码&#xff1a; if(ObjectUtil.isNotNull(temp.getUserId()) && temp.getUserId()!SecurityUtils.getUserId()) {logger.error(temp.toString());logger.error("Securi…

ICV:车规级激光雷达市场规模超7亿美元,补盲雷达有望2024年量产

全球前沿科技咨询机构ICV近期发布了车载激光雷达的市场分析报告&#xff0c;ICV在报告中表示激光雷达是自动驾驶传感器中增速最快的传感器&#xff0c;预计未来五年的复合年增长率达43.4%。此外&#xff0c;混合固态式激光雷达近五年内将仍以应用转镜技术为主。 本报告旨在评估…

【store商城项目05】新增收获地址的开发

新增收获地址的开发1.创建地址表2.创建实体类3.持久层的开发3.1规划需要执行的SQL语句3.2Mapper接口与抽象方法3.3配置SQL映射3.4测试4.业务层的开发4.1规划异常4.2接口和抽象方法4.3实现抽象方法4.4测试5.控制层的开发5.1规划异常5.2设计请求5.3处理请求5.4测试6前端页面1.创建…

【Linux】Linux权限(二)默认权限的来源

默认权限1.默认权限2.默认权限&#xff08;最终权限&#xff09;由谁决定2.1起始权限2.2umask&#xff08;权限掩码&#xff09;2.3 最终权限的计算3.总结1.默认权限 在Linux下&#xff0c;我们以普通用户创建一个普通文件&#xff0c; 这个普通文件(这里不包括可执行)的默认权…

萤石网络IPO首日破发:市值缩水20亿元,海康威视为控股股东

12月28日&#xff0c;杭州萤石网络股份有限公司&#xff08;下称“萤石网络”&#xff0c;SH:688475&#xff09;在上海证券交易所科创板上市。本次上市&#xff0c;萤石网络的发行价为28.77元/股&#xff0c;发行1.13亿股&#xff0c;募资总额为32.51亿元&#xff0c;总市值约…

【1.1】认识微服务--服务架构演变

认识微服务--服务架构演变单体架构分布式架构服务治理微服务微服务架构特征小结知识内容来自于黑马程序员视频教学和百度百科。博主仅作笔记整理便于回顾学习。如有侵权请私信我。 单体架构 单体架构&#xff1a; 将业务的所有功能集中在一个项目中开发&#xff0c;打成一个包…

线性规划求解-MATLAB Lingo Python实现

线性规划求解-MATLAB Lingo Python实现 线性规划 线性规划是辅助人们进行科学管理的一种数学方法&#xff0c;是研究线性约束条件下线性目标函数的极值问题的数学理论和方法。其展开形式可以表示为如下形式&#xff1a; Max⁡(Min⁡)zc1x1c2x2…cnxns.t. {a11x1a12x2⋯a1nxn≥…