Java多线程:线程组

news2024/11/8 21:26:17

线程组

可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的组织结构有点类似于树的形式,如图所示:

线程组的作用是:可以批量管理线程或线程组对象,有效地对线程或线程组对象进行组织。

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

所谓1级关联就是父对象中有子对象,但并不创建孙对象。这种情况在开发中很常见,比如创建一些线程时,为了有效对这些线程进行阻止管理,通常情况下是创建一个线程组,然后再将部分线程归属到该组中,以此来对零散的线程对象进行有效的管理。

看一下简单的1级关联的例子:

public class MyThread49 implements Runnable {

        public void run() {

            try {

                while (!Thread.currentThread().isInterrupted()) {

                    System.out.println("ThreadName = " + Thread.currentThread().getName());

                    Thread.sleep(3000);

                }

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

    public static void main(String[] args) {

        MyThread49 mt0 = new MyThread49();

        MyThread49 mt1 = new MyThread49();

        ThreadGroup tg = new ThreadGroup("新建线程组1");

        Thread t0 = new Thread(tg, mt0);

        Thread t1 = new Thread(tg, mt1);

        t0.start();

        t1.start();

        System.out.println("活动的线程数为:" + tg.activeCount());

        System.out.println("线程组的名称为:" + tg.getName());

    }

看一下运行结果:

活动的线程数为:2

ThreadName = Thread-1

ThreadName = Thread-0

线程组的名称为:新建线程组1

ThreadName = Thread-1

ThreadName = Thread-0

ThreadName = Thread-1

ThreadName = Thread-0

ThreadName = Thread-1

ThreadName = Thread-0

...

控制台上打印出的信息表示线程组中有两个线程,并且打印出了线程组的名称。另外,两个线程无限隔3秒打印,也符合代码预期

线程关联线程组:多级关联

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

多级关联的代码就不写了,简单看一下怎么使用关机关联,查看下JDK API的ThreadGroup构造方法:

注意一下第二个,假如要使用多级关联一般就是用第二个构造函数。第一个参数表示新线程组的父线程组,第二个参数表示新线程组的名称,有了父线程组和新线程组的名称,自然可以构造出一个新的线程组来了。

当然用第一个构造方法也是可以的,下一部分就会提到。

另外注意一点,线程必须启动后才能归到指定线程组中。

线程组自动归属特性

自动归属的意思就是自动归到当前线程组中,看一下例子:

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

第一个线程组名称为:新的组

从结果看,实例化了一个group出来,没有指定线程组,那么自动归到当前线程所属的线程组中,也就是隐式地在一个线程组中添加了一个子线程组。

根线程组

看一下根线程组: 

public static void main(String[] args) {

        System.out.println(Thread.currentThread().getThreadGroup().getParent().getName());

        System.out.println(Thread.currentThread().getThreadGroup().getParent().getParent().getName());

    }

看一下运行结果:

system

Exception in thread "main" java.lang.NullPointerException

at com.xrq.example.e49.TestMain49.main(TestMain49.java:11)

运行结果可以得出两个结论:

1、根线程组就是系统线程组system

2、抛空指针异常是因为系统线程组上已经没有线程组了,所以system的getParent()方法返回的是null,对null调用getName()方法自然是NullPointerException

关于根线程组,看一下ThreadGroup的源码:

/**

* Creates an empty Thread group that is not in any Thread group.

* This method is used to create the system Thread group.

*/

private ThreadGroup() { // called from C code

this.name = "system";

this.maxPriority = Thread.MAX_PRIORITY;

}

一个私有构造方法,说明不是对开发者开放的。注释上已经写得很清楚了,这是C代码调用的,用于构建系统线程组。

批量停止组内线程

使用线程组自然是要对线程做批量管理的,到目前为止我们似乎都没有看见如何对线程组内的线程做批量操作,最后来看一下批量操作线程组内的线程:

public class MyThread50 extends Thread {

        public MyThread50(ThreadGroup tg, String name) {

            super(tg, name);

        }

        public void run() {

            System.out.println("ThreadName = " + Thread.currentThread().getName() +

                "准备开始死循环了");

            while (!this.isInterrupted()) {
            }

            System.out.println("ThreadName = " + Thread.currentThread().getName() +

                "结束了");

        }

    }

    开3个线程:

    public static void main(String[] args) throws InterruptedException {

        ThreadGroup tg = new ThreadGroup("我的线程组");

        MyThread50 mt = null;

        for (int i = 0; i < 3; i++) {

            mt = new MyThread50(tg, "线程" + i);

            mt.start();

        }

        Thread.sleep(5000);

        tg.interrupt();

        System.out.println("调用了interrupt()方法");

    }

看一下运行结果:

ThreadName = 线程0准备开始死循环了

ThreadName = 线程2准备开始死循环了

ThreadName = 线程1准备开始死循环了

调用了interrupt()方法

ThreadName = 线程2结束了

ThreadName = 线程1结束了

ThreadName = 线程0结束了

看到调用了ThreadGroup中的interrupt()方法批量中断了线程组内的线程,这就是ThreadGroup的作用。更多线程组的操作可以查看JDK API。

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

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

相关文章

从4k到42k,软件测试工程师的涨薪史,给我看哭了

清明节一过&#xff0c;盲猜大家已经无心上班&#xff0c;在数着日子准备过五一&#xff0c;但一想到银行卡里的余额……瞬间心情就不美丽了。 最近&#xff0c;2023年高校毕业生就业调查显示&#xff0c;本科毕业月平均起薪为5825元。调查一出&#xff0c;便有很多同学表示自己…

命令行打jar包

命令行打jar包前言jar --helpcvfmMANIFEST.MF压入class文件前言 每一个java开发者运行第一个java项目时都知道项目通常被打成jar包&#xff0c;这些jar包是由IDE工具打的&#xff0c;知其然不知其所以然。 jar --help 用help命令打印jar支持的所有参数&#xff0c;不做过多解…

【GPT开发】人人都能用ChatGPT4.0做Avatar虚拟人直播

0 前言 最近朋友圈以及身边很多朋友都在研究GPT开发&#xff0c;做了各种各样的小工具小Demo&#xff0c;AI工具用起来是真的香&#xff01;在他们的影响下&#xff0c;我也继续捣鼓GPT Demo&#xff0c;希望更多的开发者加入一起多多交流。 上一篇结合即时通 IM SDK捣鼓了一个…

2023mathorcup B题

已完成完整B题C题的模型代码&#xff0c;具体看文末 摘要 城市轨道交通系统作为城市出行的重要组成部分&#xff0c;对于缓解城市交通压力、提高出行效率具有重要意义。优化列车时刻表是提高运营效率、降低企业运营成本、提高乘客满意度的关键。本研究针对城市轨道交通列车时…

SAR ADC系列24:冗余设计

目录 冗余&#xff08;Redundancy&#xff09; 比较器出错&#xff1a;原因 比较器出错&#xff1a;后果 引入冗余&#xff1a;纠错 冗余&#xff1a;容错量 冗余&#xff1a;非二进制CDAC --sub二进制 冗余&#xff1a;提速 另一种冗余设计方法&#xff1a; 下面的关…

tab栏切换

效果&#xff1a; 当鼠标通过上边tab栏时&#xff0c;对应的元素变亮并切换到相应的菜单 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge…

英语学渣如何成功逆袭?聊聊我获得海外工作的真实经历

今天我想和大家分享一下作为一个英语学渣&#xff0c;我是如何成功找到一份海外工作的。希望能够给和我有相似经历的小伙伴们一些启示。以下是兴哥一个女粉丝成功逆袭的经历&#xff0c;大家可以一起旁观一下她的自白。 首先&#xff0c;让我简单介绍一下我的情况。我现在在芬…

【云原生概念和技术】1.2 云原生技术概括(上)

如果想了解或者学习云原生的友友们&#xff0c;欢迎订阅哦&#xff5e;&#x1f917;&#xff0c;目前一周三更&#xff0c;努力码字中&#x1f9d1;‍&#x1f4bb;…目前第一章是一些介绍和概念性的知识&#xff0c;可以先在脑海里有一个知识的轮廓&#xff0c;从第二章开始就…

window eNSP安装使用教程

1&#xff0c;需要的安装包&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1U38OENqOeKXDN0-ipFTxwA?pwdsd12 提取码&#xff1a;sd12 安装eNSP 根据提示&#xff1a;需要先安装wireshark, VirtualBox, winPcap,所以我们接下来先依次安装上面三个安装包。 1&#x…

教育大数据总体解决方案(3)

为区县教育局提供标准制定、流程把控、实施监控、决策支持等服务&#xff0c;支持在全市统一的评价指标体系基础上&#xff0c;为各个区县提供个性化定制功能&#xff0c;各县能够在市统一评价指标体系内任意调整、增加二三级评价指标项&#xff0c;并可以调整对应指标项的分数…

逍遥自在学C语言 | 位运算符<<的高级用法

前言 在上一篇文章中&#xff0c;我们介绍了~运算符的高级用法&#xff0c;本篇文章&#xff0c;我们将介绍<< 运算符的一些高级用法。 一、人物简介 第一位闪亮登场&#xff0c;有请今后会一直教我们C语言的老师 —— 自在。 第二位上场的是和我们一起学习的小白程序猿…

带你们偷瞄编程绕不开的C语言(二)

&#x1f929;&#xff1a;大家好&#xff0c;我是paperjie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 &#x1f970;&#xff1a;这里是C专栏&#xff0c;笔者用重金(时间和精力)打造&#xff0c;基础知识一网打尽&#xff0c;希望可以帮到读者们哦。 &#x1f…

常见面试题之MQ篇

1.1.你们为什么选择了RabbitMQ而不是其它的MQ&#xff1f; 如图&#xff1a; 话术&#xff1a; kafka是以吞吐量高而闻名&#xff0c;不过其数据稳定性一般&#xff0c;而且无法保证消息有序性。我们公司的日志收集也有使用&#xff0c;业务模块中则使用的RabbitMQ。 阿里巴…

SQL——子查询

在SQL语言中&#xff0c;一个SELECT&#xff0d;FROM&#xff0d;WHERE语句 称为一个查询块。 子查询(或内层查询)是一个 SELECT 查询,它嵌套在 (1)SELECT、UPDATE、INSERT、DELETE 语句的 WHERE 、 (2)带GROUP BY 的 HAVING 子句内&#xff0c; (3)或其它子查询中 (与比较(6个…

JDBC MySQL ORM 实现登录功能(避免SQL注入)

目录 一、创建数据库表 二、创建Users类 三、登录类 四、存在的漏洞 &#xff08;1&#xff09;SQL注入 &#xff08;2&#xff09;分析 &#xff08;3&#xff09;补救 一、创建数据库表 CREATE DATABASE jdbcdatabase;CREATE TABLE IF NOT EXISTS user( uid INT PRIMARY KE…

windows 配置 libxml2

1、下载需要的包 1&#xff09;libconv LibIconv for Windows 2) libxml2 Releases GNOME / libxml2 GitLab 2、配置文件 将 libxml2 的包解压到一个目录&#xff0c;并在该目录下创建 include 和 lib 目录 将如下的 iconv.h 复制到新建的 include 目录 路径&#xff…

013 - C++引用

本期我们要讲的是 C 中的引用。 上期我们讨论了指针&#xff0c;如果你没有看过那期内容&#xff0c;你一定要回去看看&#xff0c;因为引用实际上只是指针的扩展&#xff0c;你至少需要在基本层面上理解指针是如何工作的&#xff0c;然后才能继续学习本期的内容&#xff0c;本…

UI Toolkit(1)

UI ToolkitUI Toolkit界面画布设置背景制作UI布局UI Toolkit界面 在Unity 2021LTS版本之后UI Toolkit也被内置在Unity中&#xff0c;Unity有意的想让UI Toolkit 成为UI的主要搭建方式&#xff0c;当然与UGUI相比还是有一定的差别。他们各有有点&#xff0c;这次我们就开始介绍…

【Homebrew】MacBook的第二个AppStore

英文官网&#xff1a;Homebrew — The Missing Package Manager for macOS (or Linux) 中文官网&#xff1a;macOS&#xff08;或 Linux&#xff09;缺失的软件包的管理器 — Homebrew 1 简介 Homebrew 由开发者 Max Howell 开发&#xff0c;并基于 BSD 开源&#xff0c;是一…

基于K-最近邻算法构建红酒分类模型

基于K-最近邻算法构建红酒分类模型 描述 Wine红酒数据集是机器学习中一个经典的分类数据集&#xff0c;它是意大利同一地区种植的葡萄酒化学分析的结果&#xff0c;这些葡萄酒来自三个不同的品种。数据集中含有178个样本&#xff0c;分别属于三个已知品种&#xff0c;每个样本…