Java并发编程实战 05 | 什么是线程组?

news2025/1/10 21:12:54

1.线程组介绍

在 Java 中,ThreadGroup 用于表示一组线程。通过 ThreadGroup,我们可以批量控制和管理多个线程,使得线程管理更加方便。

ThreadGroup 和 Thread 的关系就像它们的字面意思一样简单:每个线程 (Thread) 必定属于一个线程组 (ThreadGroup),线程不能脱离线程组而单独存在。

例如,方法 main() 中的线程名称是 main,如果在执行 new Thread() 时没有明确指定其 ThreadGroup,那么默认情况下,会将当前正在执行的线程(即父线程)的 ThreadGroup 设置为新线程的 ThreadGroup。

public class Demo {
    public static void main(String[] args) {
        Thread subThread = new Thread(() -> {
            System.out.println("The name of the thread group where subThread is located is:" +
                    Thread.currentThread().getThreadGroup().getName());
            System.out.println("The name of the current thread (subThread) is:" +
                    Thread.currentThread().getName());
        });

        subThread.start();
        System.out.println("The thread group name of the thread in which the main() method is executed is: "
                + Thread.currentThread().getThreadGroup().getName());
        System.out.println("The name of the current thread is:"
                + Thread.currentThread().getName());
    }
}

//输出:
The thread group name of the thread in which the main() method is executed is: main
The name of the current thread is:main
The name of the thread group where subThread is located is:main
The name of the current thread (subThread) is:Thread-0

一个线程组可以包含多个线程,也可以包含多个子线程组。从结构上来看,线程组是一个树形结构,每个线程都属于一个线程组,线程组之间通过父子关系连接,最终追溯到一个根线程组,即系统线程组。

  1. JVM 创建的 系统线程组(system thread group)是用于处理 JVM 系统任务的一组线程,例如对象的销毁、垃圾回收(GC)等。
  2. 系统线程组的直接子线程组是 main 线程组,其中至少包含一个用于执行 main 方法的线程。
  3. 应用程序创建的所有线程组都是 main 线程组的子线程组。

我们可以查看 JVM 创建的 system 线程组以及 main 线程组。

public static void main(String[] args) {
        ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup();
        ThreadGroup systemThreadGroup = mainThreadGroup.getParent();
        System.out.println("The name of the parent thread group of the thread group where the current thread is located = " + systemThreadGroup.getName());
        System.out.println("The name of the thread group where the current thread is located is = " + mainThreadGroup.getName());
  }
  
//输出:
The name of the parent thread group of the thread group where the current thread is located = system
The name of the thread group where the current thread is located is = main

线程可以访问其所属的线程组的信息,但无法访问该线程组的父线程组或其他线程组的信息。

线程组构成

首先,让我们看看 ThreadGroup 源码中的成员变量。

public class ThreadGroup implements Thread.UncaughtExceptionHandler {
     父线程组
    private final ThreadGroup parent; 
    String name; 
    int maxPriority;
    boolean destroyed;
    boolean daemon;
    boolean vmAllowSuspension;

    int nUnstartedThreads = 0;
    //子线程的数量
    int nthreads;   
    //子线程的数组
    Thread threads[]; 

    //子线程组的数量
    int ngroups; 
    //子线程组的数组
    ThreadGroup groups[];
}

接下来,我们来看一下 ThreadGroup 提供的两个构造函数。我会在代码中添加一些注释,以帮助大家更好地理解它们的功能和用法。

// JVM启动时调用,创建根线程组。
private ThreadGroup() { 
    this .name = "system" ; 
    this .maxPriority = Thread.MAX_PRIORITY; 
    this .parent = null ; 
} 
//默认传入当前ThreadGroup作为父ThreadGroup,新线程组的父线程组就是当前运行线程的线程组。
public ThreadGroup(String name) { 
    this (Thread.currentThread().getThreadGroup(), name); 
} 
//传入名称创建线程组,父线程由客户端指定。
public ThreadGroup(ThreadGroup parent, String name) { 
    this (checkParentAccess(parent), parent, name); 
} 
//主私有构造函数,大部分参数继承自父线程组
private ThreadGroup(Void unused, ThreadGroup parent, String name) {
    this.name = name;
    this.maxPriority = parent.maxPriority;
    this.daemon = parent.daemon;
    this.vmAllowSuspension = parent.vmAllowSuspension;
    this.parent = parent;
    parent.add(this);
}

代码中的checkParentAccess() 方法用于验证当前线程是否具备对线程组进行修改的权限。这是为了确保线程组的安全性和一致性。

下面我将演示这两个构造函数的使用示例:

public class ConstructDemo {
    public static void main(String[] args) {
        ThreadGroup subThreadGroup1 = new ThreadGroup("subThreadGroup1");
        ThreadGroup subThreadGroup2 = new ThreadGroup(subThreadGroup1, "subThreadGroup2");
        System.out.println("subThreadGroup1 parent name is: " + subThreadGroup1.getParent().getName());
        System.out.println("subThreadGroup2 parent name is: " + subThreadGroup2.getParent().getName());
    }
}

//输出:
subThreadGroup1 parent name is: main
subThreadGroup2 parent name is: subThreadGroup1

ThreadGroup包含的方法介绍

ThreadGroup 提供了许多有用的方法,下面简要介绍一下。

我们选择了一些方法通过代码来演示其用法。

public class ThreadGroupMethodCase {

    public static void main(String[] args) throws InterruptedException {
        ThreadGroup subgroup1 = new ThreadGroup("subgroup1");
        Thread t1 = new Thread(subgroup1, "t1 in subgroup1");
        Thread t2 = new Thread(subgroup1, "t2 in subgroup1");
        Thread t3 = new Thread(subgroup1, "t3 in subgroup1");
        t1.start();
        Thread.sleep(50);
        t2.start();
        int activeThreadCount = subgroup1.activeCount();
        System.out.println("Active thread in " + subgroup1.getName() + " thread group: " + activeThreadCount);

        ThreadGroup subgroup2 = new ThreadGroup("subgroup2");
        Thread t4 = new Thread(subgroup2, "t4 in subgroup2");

        ThreadGroup currentThreadGroup = Thread.currentThread().getThreadGroup();
        int activeGroupCount = currentThreadGroup.activeGroupCount();
        System.out.println("Active thread groups in " + currentThreadGroup.getName() + " thread group: " + activeGroupCount);

        System.out.println("Prints information about currentThreadGroup to the standard output:");
        currentThreadGroup.list();
    }
}

//输出:
Active thread in subgroup1 thread group: 2
Active thread groups in main thread group: 2
Prints information about currentThreadGroup to the standard output:
java.lang.ThreadGroup[name=main,maxpri=10]
    Thread[main,5,main]
    java.lang.ThreadGroup[name=subgroup1,maxpri=10]
    java.lang.ThreadGroup[name=subgroup2,maxpri=10]

这里要注意的一点是,在输出当前线程组中的活动线程数时,只计算状态为 RUNNABLE、BLOCKED、WAITING 或 TIMED_WAITING 的线程,不包括状态为 NEW 或 TERMINATED 的线程。

因此,当我们调用 subgroup1.activeCount() 时,它实际上只会返回当前活动的线程数。举例来说,如果线程 t1 已经结束,而线程 t3 尚未启动,那么只有线程 t2 被计算在内。

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

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

相关文章

7.统一网关-Gateway

文章目录 1.统一网关介绍2.网关开发3.predicate4.Route Predicate Factories(路由断言工厂)4.1Path 路由断言工厂4.2.Method 路由断言工厂4.3 Header 路由断言工厂4.4 Query 路由断言工厂4.5 Host 路由断言工厂4.6 After 路由断言工厂4.7 Before 路由断言工厂4.8 Between 路由断…

FPGA实现串口升级及MultiBoot(二)FPGA启动流程

这个系列开篇肯定要先了解FPGA的启动流程,试想一下:我想实现MultiBoot,那么我应该在什么时候开始升级,升级失败后FPGA进行了哪些操作,以及怎么回到Golden区? 还有一个问题,就是我硬件打板回来&a…

Chrome下载视频的插件

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

SprinBoot+Vue个性化旅游推荐系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质…

数学建模_数据预处理流程(全)

数据预处理整体流程图 一般数据预处理流程 处理缺失值:填补或删除缺失值。处理异常值:检测并处理异常值。数据编码:将分类变量进行标签编码或独热编码。数据标准化/归一化:对数据进行标准化或归一化处理。连续变量离散化&#xff…

人机交互系统中的人脸讲话生成系统调研

《Human-Computer Interaction System: A Survey of Talking-Head Generation》 图片源:https://github.com/Yazdi9/Talking_Face_Avatar 目录 前言摘要一、背景介绍二、人机交互系统体系结构2.1. 语音模块2.2. 对话系统模块2.3. 人脸说话动作生成 三 人脸动作生成…

基于人工智能的语音情感识别系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 语音情感识别是人工智能的一项重要应用,旨在通过分析语音信号中的特征来判断说话者的情感状态,如“愤怒”、“…

1800 万,财务自由了

《黑神话:悟空》 距离《黑神话:悟空》上线(8 月 20 日)上线已过去半个月,从刚开始全网热议,连官方都下场点评,到现在的逐渐回归平静。 不是游戏圈或是对数据不敏感的网友,可能会落入…

【路径规划】 使用计算机视觉和机器人操纵器绘制肖像

摘要 本项目展示了使用计算机视觉和机械臂绘制肖像的完整流程。系统利用网络摄像头获取肖像图像,经过图像处理后生成路径,然后利用逆向运动学将路径转化为机械臂的运动轨迹,最终在硬件机器人上执行绘制。实验结果表明,该系统能够…

【人工智能学习笔记】2_数据处理基础

数据的概述 数据(Data)的定义 用于表示客观事物的未经加工的原始素材不仅指狭义上的数字,也只具有一定意义的文字、字母、数字符号的组合客观事物的属性、数量、位置及其相互关系的抽象表示 在计算机科学与技术领域中,数据是指…

微信小程序和普通网页有什么不同

微信小程序和普通网页的区别主要体现在文件后缀、运行原理、运行环境、开发规则以及标签名等方面。微信小程序于2016年推出,依托微信庞大的用户基础,迅速成为移动应用中的佼佼者,而普通网页则基于传统的HTML、CSS和JavaScript技术构建。以下将…

2024年四川省安全员B证证考试题库及四川省安全员B证试题解析

题库来源:安全生产模拟考试一点通公众号小程序 2024年四川省安全员B证证考试题库及四川省安全员B证试题解析是安全生产模拟考试一点通结合(安监局)特种作业人员操作证考试大纲和(质检局)特种设备作业人员上岗证考试大…

C语言深度剖析--不定期更新的第三弹

hello,everybody!最近又更新了哈,希望对大家有所帮助 switch case关键字 基本语法: switch(整型变量/常量/整型表达式){case 1:var 1;break;case 2:var 2;break;case 3:var 3;break;default:break; }switch case语句也和if语句一样具有判断和分支的功…

第4章-02-用WebDriver驱动浏览器页面截图

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年CSDN全站百大博主。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 🏆本文已收录于专栏:Web爬虫入门与实战精讲,后续完整更新内容如下。 文章…

NX重要操作函数调用流程

1.文件打开 2.鼠标移动操作 3.定时器

Vue3+Ts封装类似于Element-plus的图片预览组件

组件目录结构如下: options.ts文件用来存储配置文件, 代码如下: import {isFirefox} from ./tools;export type ImageViewerAction = zoomIn | zoomOut | clocelise | anticlocelise;export const mousewheelEventName = isFirefox() ? DOMMouseScroll : mousewheel;// 键…

自然语言处理系列五十三》文本聚类算法》文本聚类介绍及相关算法

注:此文章内容均节选自充电了么创始人,CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》(人工智能科学与技术丛书)【陈敬雷编著】【清华大学出版社】 文章目录 自然语言处理系列五十三文本聚类算法》文本聚类介绍及相关算法K…

isalnum函数讲解 <ctype.h>头文件函数

目录 ​1.头文件 2.isalnum函数讲解​​​​​​​ 方源一把抓住VS2022&#xff0c;顷刻 炼化&#xff01; 1.头文件 以上函数都需要包括头文件<ctype.h> &#xff0c;其中包括 isalnum 函数 #include<ctype.h> 2.isalnum函数讲解 isalnum函数是一种判断字符…

解决:Module build failed (from ./node_modules/sass-loader/dist/cjs.js)问题

一、问题 Module build failed (from ./node_modules/sass-loader/dist/cjs.js): Error: Cannot find module sass 二、解决方法 1.清除缓存 npm cache clean --force2.重构项目 npm install 3.更新&#xff08;获取最新的&#xff09;node-sass和sass-loader依赖包 npm …

OpenAI SORA团队负责人 通往智能的方式 报告笔记

OpenAI SORA团队负责人 通往智能的方式 报告笔记 这个报告其实是2024年智源大会的主旨报告&#xff0c;OpenAI SORA和DALL-E团队负责人Aditya Ramesh给出的一段有关多模态大模型的报告。我去听了现场&#xff0c;感觉倍受启发&#xff0c;但是感觉很多并不能当场理解&#xff…