java多线程学习- 下

六. 线程管理

6.1 线程组

类似于在计算机中使用文件夹管理文件, 也可以使用线程组来管理线程,在线程组中定义一组相似(相关)的线程. 在线程组中也可以定义子线程组,
Thread 类有几个构造方法允许在创建线程时指定线程组,如果创建线程时没有指定线程组则该线程就属于浮现出所在的线程组, JVM 在创建main 线程时会为他指定一个线程组,因此每个java线程都有一个线程组与之关联,可以调用线程getThreadGroup方法返回线程组.
线程组开始时处于安全的考虑设计用来区分不同的Applet,然而ThreadGroup 并未实现这一目标 ,在新开发的系统中,已经不常用线程组.
现在一般会将一组相关的线程存入一个数组或一个集合中, 如果仅仅是用来区分线程时,可以使用线程名称来区分. 多数情况下,可以忽略线程组.

6.1.1 创建线程组

package com.company.threadgroup;/***  演示创建线程组,*/
public class Test01 {public static void main(String[] args) {// 1.返回当前main 线程的线程组ThreadGroup mianGroup = Thread.currentThread().getThreadGroup();System.out.println(mianGroup.toString()); // java.lang.ThreadGroup[name=main,maxpri=10]// 2.定义线程组,如果不指定所属线程组,则自动归属到当先线程所属的线程组中ThreadGroup group1 = new ThreadGroup("group1");System.out.println(group1); // java.lang.ThreadGroup[name=group1,maxpri=10]// 3. 定义线程组,同时指定父线程组ThreadGroup group2 = new ThreadGroup(mianGroup, "group2");// 现在group1 与group2 都是mainGroup 线程组中的子线程组System.out.println(group1.getParent() == mianGroup); // trueSystem.out.println(group2.getParent() == mianGroup); // true// 4 在创建线程时指定所属线程组Runnable r = new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread());}};// 在创建线程时, 如果没有指定线程组,则默认线程归属到父线程的线程组中。// 在main 线程中 创建了t1 线程,称main线程为父线程,t1线程称为子线程,t1没有指定线程组,则t1 线程就归属与父线程的线程组中Thread t1 = new Thread(r, "t1");System.out.println(t1); // Thread[t1,5,main] t1的线程组是main// 创建线程时,可以指定线程所属线程组Thread t2 = new Thread(group1, r, "t2");Thread t3 = new Thread(group2, r, "t3");System.out.println(t2); // Thread[t2,5,group1]System.out.println(t3); // Thread[t3,5,group2]}
}

6.1.2 线程组的基本操作

activeCount() 返回当前线程组及子线程组中活动线程的数量(近似值)
activeGroupCount() 返回当前线程组及子线程组中的数量(近似值)
int enumerate(Threat[] list) 将当前线程组中的活动线程复制到参数数组中。
enumerate(ThreadGroup[] list)将当前线程组中的活动线程组复制到参数数组中。
getMaxPriotity 返回线程组的最大优先级,默认是10.
getName() 返回线程组的名称
getParent()返回父线程组
interrupt() 中断线程组中所有的线程
isDaemon() 判断当前线程组是否为守护线程
list() 将当前线程组中的活动线程打印出来。

parentOf(ThreadGroup g) 判断当前线程组中是否为参数线程组的父线程组。
setDaemon(boolean daemon)设置线程组为守护线程组


/*** 演示线程组的基本操作*/
public class Test02 {public static void main(String[] args) {ThreadGroup mianGroup = Thread.currentThread().getThreadGroup(); // 返回当前线程组// 在定义线程组ThreadGroup group = new ThreadGroup("group"); // 默认group的父线程组是main线程组Runnable r = new Runnable() {@Overridepublic void run() {while (true) {System.out.println("------- 当前线程" + Thread.currentThread());try{Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};Thread t1 =  new Thread(r,"t1"); // 默认在main线程组中创建线程Thread t2 =  new Thread(group,"t2"); // 在指定的group 线程组中创建线程t1.start();t2.start();System.out.println("main 线程组中活动线程数量:" + mianGroup.activeCount()); // 4, main线程组中活动线程: main,t1,t2, 垃圾回收器System.out.println("group 子线程组中活动线程数量:" + group.activeCount()); // 1, t2System.out.println("main 线程组中子线程组数量:" + mianGroup.activeGroupCount()); //1 groupSystem.out.println("group 子线程组中子线程组数量:" + group.activeGroupCount());// 0System.out.println("main 线程组的父线程组:" + mianGroup.getParent()); // mian 线程组的父线程组是systemSystem.out.println("group 线程组的父线程组:" + group.getParent()); // mainSystem.out.println(mianGroup.parentOf(mianGroup)); // true , 线程组也是他自己的父线程组System.out.println(mianGroup.parentOf(group));// truemianGroup.list(); // 把main 线程组中所有的线程打印输出}
}

6.1.3 复制线程组中的线程及子线程组

enumerate(Thread[] list) 把当前线程组和子线程组中所有的线程复制到参数数组中;
enumerate(Thread[] list,boolean recursive) 如果第二个参数设置为false ,则只复制当前线程组中所有的线程,不复制子线程组中的线程
enumerate (ThreadGroup[] list) 把当前线程组和子线程组中所有的线程组复制到参数数组中;
enumerate (ThreadGroup[] list, boolean recursive)第二个参数设置为false,则只复制当前线程组的子线程组。

/*** 演示复制线程组中的内容*/
public class Test03 {public static void main(String[] args) {ThreadGroup mainGroup =  Thread.currentThread().getThreadGroup(); // 返回main线程的main线程组// 创建线程组ThreadGroup group1 = new ThreadGroup("group1"); // 默认group1的父线程组就是当前线程的mainThreadGroup group2 = new ThreadGroup(mainGroup,"group1"); // 默认group1的父线程组就是当前线程的mainRunnable runnable = new Runnable() {@Overridepublic void run() {System.out.println(" -- 当前线程:" + Thread.currentThread());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}};// 创建三个线程Thread t1 = new Thread(runnable,"t1"); // 默认在main 线程组中创建线程Thread t2 = new Thread(group1, runnable,"t2"); // 在group1 线程组中创建线程Thread t3 = new Thread(group2, runnable,"t3"); // 在group2 线程组中创建线程t1.start();t2.start();t3.start();//1、 把main 线程组中的线程复制到数组中// 先定义存储线程的数组,数组的长度为main线程组中活动线程的数量Thread[] threadList = new Thread[mainGroup.activeCount()];
//        //把main 线程组中包括子线程组中的所有的线程复制到数组中
//        mainGroup.enumerate(threadList);
//        for (Thread thread:threadList
//             ) {
//            System.out.println(thread);
//            /*
//            输出:
//            Thread[Monitor Ctrl-Break,5,main]
//            Thread[t1,5,main]
//            Thread[t2,5,group1]
//            Thread[t3,5,group1]
//            */
//        }// 只把main 线程组中的线程复制到数组中,不包含子线程组中的线程System.out.println("----------------");mainGroup.enumerate(threadList, false);for (Thread thread:threadList) {System.out.println(thread);/*输出:Thread[Monitor Ctrl-Break,5,main]Thread[t1,5,main]Thread[t2,5,group1]Thread[t3,5,group1]*/}// 2) 把main 线程组中的子线程组复制到数组中// 定义数组存储线程组ThreadGroup[] threadGroups = new ThreadGroup[mainGroup.activeCount()];// 把main 线程在中的子线程组复制到数组中mainGroup.enumerate(threadGroups);System.out.println("==================");for(ThreadGroup threadGroup: threadGroups) {System.out.println(threadGroup);/*** ava.lang.ThreadGroup[name=group1,maxpri=10]* java.lang.ThreadGroup[name=group1,maxpri=10]* null* null*/}}
}

6.1.4 线程组的批量中断

线程组中interrupt()方法,可以给该线程组中所有的活动线程添加中断标识
如果中断睡眠中的线程,产生中断异常, 同时会清除中断标识

/*** 线程组的批量中断*/
public class Test04 {public static void main(String[] args) throws InterruptedException {Runnable r = new Runnable() {@Overridepublic void run() {System.out.println("当前线程---" + Thread.currentThread() + "-- 开始循环");// 当线程没有被中断就一直循环while (!Thread.currentThread().isInterrupted()) {System.out.println(Thread.currentThread().getName() + "===");
//                    try {
//                        Thread.sleep(2000);
//                    } catch (InterruptedException e) {
//                        // 如果中断睡眠中的线程,产生中断异常, 同时会清除中断标识
//                        e.printStackTrace();
//                    }}System.out.println

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

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

相关文章

STM32-新建工程(标准库)

目录 STM32F10x新建工程(标准库) 移植文件夹 新建工程 添加启动文件和必需文件 在工程中加载新添加的文件 在工程中添加文件路径 在工程中添加main函数 添加lib库 添加必需文件 添加宏定义 STM32F10x新建工程(标准库) …

【Python】创建简单的Python微服务Demo与FastAPI

创建简单的Python微服务Demo与FastAPI 在微服务架构中,通过FastAPI框架创建一个简单的Python微服务Demo涉及多个步骤,包括定义服务、使用框架、进行通信等。在这篇文章中,我们将使用FastAPI框架创建两个简单的微服务,它们通过RES…

HBase安装配置:一键自动安装配置

使用shell脚本一键下载、安装、配置HBase(单机版) 1. 把下面的脚本复制保存为/tmp/install_hbase.sh文件 #!/bin/bash# 安装之前确保安装目录有写入权限,若没有,自行增加 # 安装版本 zk_version"2.4.8" # 安装目录 zk…

【WxPusher】消息推送小案例

提示:以下是本篇文章正文内容,下面案例可供参考 WxPusher后台 WxPusher文档 一、注册WxPusher 进入后台获取你的token 二、使用步骤 1.编写脚本 参数如下(示例): {"appToken": "AT_AnXubGNGCe7OVN…

基于Java SSM企业用电管理系统

企业用电管理系统是供电部门对所辖区域的企业用电进行管理的系统,假设企业全部采用分时电表,分谷(低谷时段)、峰(高峰时段)时段分别计量。系统涉及的信息及操作有: 用电企业:用电企业编号、用电企业名、地址、电话、联系人等。 电…

基于springboot的校园二手市场

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

Redis skiplist源码解析(支持范围查询)

跳表是一个多层的有序链表,在跳表中进行查询操作时,查询代码可以从最高层开始查询。层数越高,结点数越少,同时高层结点的跨度会比较大。因此,在高层查询结点时,查询一个结点可能就已经查到了链表的中间位置…

LeetCode:2477. 到达首都的最少油耗(DFS C++、Java)

目录 2477. 到达首都的最少油耗 题目描述: 实现代码与解析: dfs 2477. 到达首都的最少油耗 题目描述: 给你一棵 n 个节点的树(一个无向、连通、无环图),每个节点表示一个城市,编号从 0 到 n…

医院预约挂号平台的设计与实现

摘 要 网络的空前发展给人们的工作和生活带来了极大的便利,信息技术已成为节约运营成本、提高工作效率的首选。相比之下,国内相当多的中小医院在医院预约工作中的手工工作比较保守,数据查询和存储成本都很高,但效率很低。为了使医…

JAVAEE初阶 多线程基础(六)

wait,notify,饿汉模式 一.wait,notify方法使用1.1 例子 二.wait和sleep区别三.单例模式中的饿汉模式 一.wait,notify方法使用 引入wait和notify为了能够从应用层面上,干预到多个不同线程代码的执行顺序,不是影响系统的线程调度策略. 相当于是在应用程序代码中,让后执行的线程,主…

支付宝沙箱支付

1. 二维码 1.1 什么是二维码: ​ 二维码又称QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型。 ​ 二维条码/二维码&…

leetcode LCR 083. 全排列

Problem: LCR 083. 全排列 思路 使用一个visited数组来记录每一轮递归中数字被使用情况,dfs Code /*** param {number[]} nums* return {number[][]}*/ var permute function(nums) {const len nums.lengthconst cur [] // 当前轮次的排列结果const res [] /…

【2023.12.4练习】数据库知识点复习测试

概论 数据表:用于存储现实中数据的联系。 储存信息联系。 字段:又称列,如姓名、年龄、编号等。 记录:又称元组,为数据表中的一行,代表了一个实体的信息。 数据库(DB)&#xff1…

HNU-电路与电子学-2017期末B卷(不含解析)

【写在前面】 电路与电子学好像是从2020级开设的课程,故实际上目前只有2020与2021两个年级考过期末考试。 这门课程主要由所谓的“数电”与“模电”组成。而且先学的“模电”后学的“”数电,故期中考试主要以“模电”为主,期末考试主要以“…

C语言变长参数及其陷阱

C语言变长参数及其陷阱 C 工具 变长参数列表 这部分解释了旧的 C 风格变长参数列表。了解这些内容很重要,因为你可能会在遗留代码中遇到它们。然而,在新代码中,你应该使用变参模板来实现类型安全的变长参数列表。 考虑 C 函数 printf()&a…

04数据平台Flume

Flume 功能 Flume主要作用,就是实时读取服务器本地磁盘数据,将数据写入到 HDFS。 Flume是 Cloudera提供的高可用,高可靠性,分布式的海量日志采集、聚合和传输的系统工具。 Flume 架构 Flume组成架构如下图所示: A…

watch的 防抖 防止多次调用请求

watch监听数据变化时,如果数据变化频繁,就会导致watch函数被多次调用,从而发生多次请求的情况。解决这个问题的方法是使用防抖或节流函数来限制函数的调用频率。下面是一个使用lodash库中的防抖函数解决watch多次请求问题的例子: …

常见数据文件存储和读取

当我们使用 Python 读取数据文件时,首先推荐的就是通过 Pandas 完成,Pandas 几乎支持所有常见的数据文件格式。 数据类型文件格式读取方式存储方式文本CSVread_csvto_csv文本JSONread_jsonto_json文本HTMLread_htmlto_html文本剪切板read_clipboardto_c…

ios上传图片旋转问题解决方案(vant上传图片)

使用 van-uploader(vant 组件库上传图片组件)上传图片时, 部分 ios 机型,会偶发从手机上传图片后,图片预览中,图片旋转了 90 度的问题。 对于该问题,vant 官网中也给出了解决方案。 但官网中的方案适配的是单选情况下…

编译原理:NFA转DFA(原理+完整代码+可视化实现)

NFA转换为DFA 【本文内容摘要】 什么是DFA通过子集构造法将NFA转换为DFA生成DFA的dot文件并且形成可视化。 如果本文对各位看官有用的话,请记得给一个免费的赞哦(收藏也不错)! 文章目录 NFA转换为DFA一、什么是DFA二、NFA转换为…