Java中使用ThreadGroup类来代表线程组,表示一组线程的集合,可以对一批线程和线程组进行管理。可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的组织结构有点类似于树的形式,如图所示。

用户创建的所有线程都属于指定线程组,如果没有显式指定属于哪个线程组,那么该线程就属于默认线程组(即main线程组)。默认情况下,子线程和父线程处于同一个线程组。

此外,只有在创建线程时才能指定其所在的线程组,线程运行中途不能改变它所属的线程组,也就是说线程一旦指定所在的线程组就不能改变。

二.为什么要使用线程组

1.安全

同一个线程组的线程是可以相互修改对方的数据的。但如果在不同的线程组中,那么就不能“跨线程组”修改数据,可以从一定程度上保证数据安全。

2.批量管理

可以批量管理线程或线程组对象,有效地对线程或线程组对象进行组织或控制。

三.线程组使用示例

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

所谓一级关联就是父对象中有子对象,但并不创建孙对象。比如创建一个线程组,然后将创建的线程归属到该组中,从而对这些线程进行有效的管理。代码示例如下:

  1. public class ThreadGroupTest {
  2. public static void main(String[] args) {
  3. ThreadGroup rootThreadGroup = new ThreadGroup("root线程组");
  4. Thread thread0 = new Thread(rootThreadGroup, new MRunnable(), "线程A");
  5. Thread thread1 = new Thread(rootThreadGroup, new MRunnable(), "线程B");
  6. thread0.start();
  7. thread1.start();
  8. }
  9. }
  10. class MRunnable implements Runnable {
  11. @Override
  12. public void run() {
  13. while (!Thread.currentThread().isInterrupted()) {
  14. System.out.println("线程名: " + Thread.currentThread().getName()
  15. + ", 所在线程组: " + Thread.currentThread().getThreadGroup().getName()) ;
  16. try {
  17. Thread.sleep(1000);
  18. } catch (InterruptedException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. }
  23. }
  24. 复制代码

执行结果如下:

  1. 线程名: 线程A, 所在线程组: root线程组
  2. 线程名: 线程B, 所在线程组: root线程组
  3. 复制代码

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

所谓的多级关联就是父对象中有子对象,子对象中再创建孙对象也就出现了子孙的效果了。比如使用下图第二个构造方法,将子线程组归属到某个线程组,再将创建的线程归属到子线程组,这样就会有线程树的效果了。

代码示例如下:

  1. public class ThreadGroupTest {
  2. public static void main(String[] args) {
  3. ThreadGroup rootThreadGroup = new ThreadGroup("root线程组");
  4. Thread thread0 = new Thread(rootThreadGroup, new MRunnable(), "线程A");
  5. Thread thread1 = new Thread(rootThreadGroup, new MRunnable(), "线程B");
  6. thread0.start();
  7. thread1.start();
  8. ThreadGroup threadGroup1 = new ThreadGroup(rootThreadGroup, "子线程组");
  9. Thread thread2 = new Thread(threadGroup1, new MRunnable(), "线程C");
  10. Thread thread3 = new Thread(threadGroup1, new MRunnable(), "线程D");
  11. thread2.start();
  12. thread3.start();
  13. }
  14. }
  15. class MRunnable implements Runnable {
  16. @Override
  17. public void run() {
  18. while (!Thread.currentThread().isInterrupted()) {
  19. System.out.println("线程名: " + Thread.currentThread().getName()
  20. + ", 所在线程组: " + Thread.currentThread().getThreadGroup().getName()
  21. + ", 父线程组: " + Thread.currentThread().getThreadGroup().getParent().getName());
  22. try {
  23. Thread.sleep(1000);
  24. } catch (InterruptedException e) {
  25. e.printStackTrace();
  26. }
  27. }
  28. }
  29. }
  30. 复制代码

执行结果如下:

  1. 线程名: 线程A, 所在线程组: root线程组, 父线程组: main
  2. 线程名: 线程B, 所在线程组: root线程组, 父线程组: main
  3. 线程名: 线程C, 所在线程组: 子线程组, 父线程组: root线程组
  4. 线程名: 线程D, 所在线程组: 子线程组, 父线程组: root线程组
  5. 复制代码

3.批量管理组内线程

使用线程组自然是要对线程进行批量管理,比如可以批量中断组内线程,代码示例如下:

  1. public class ThreadGroupTest {
  2. public static void main(String[] args) {
  3. ThreadGroup rootThreadGroup = new ThreadGroup("root线程组");
  4. Thread thread0 = new Thread(rootThreadGroup, new MRunnable(), "线程A");
  5. Thread thread1 = new Thread(rootThreadGroup, new MRunnable(), "线程B");
  6. thread0.start();
  7. thread1.start();
  8. ThreadGroup threadGroup1 = new ThreadGroup(rootThreadGroup, "子线程组");
  9. Thread thread2 = new Thread(threadGroup1, new MRunnable(), "线程C");
  10. Thread thread3 = new Thread(threadGroup1, new MRunnable(), "线程D");
  11. thread2.start();
  12. thread3.start();
  13. rootThreadGroup.interrupt();
  14. System.out.println("批量中断组内线程");
  15. }
  16. }
  17. class MRunnable implements Runnable {
  18. @Override
  19. public void run() {
  20. while (!Thread.currentThread().isInterrupted()) {
  21. System.out.println("线程名: " + Thread.currentThread().getName()
  22. + ", 所在线程组: " + Thread.currentThread().getThreadGroup().getName()
  23. + ", 父线程组: " + Thread.currentThread().getThreadGroup().getParent().getName());
  24. try {
  25. Thread.sleep(1000);
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. break;
  29. }
  30. }
  31. System.out.println(Thread.currentThread().getName() + "执行结束");
  32. }
  33. }
  34. 复制代码

执行结果如下:

  1. 线程名: 线程A, 所在线程组: root线程组, 父线程组: main
  2. 线程名: 线程B, 所在线程组: root线程组, 父线程组: main
  3. 线程名: 线程C, 所在线程组: 子线程组, 父线程组: root线程组
  4. 线程名: 线程D, 所在线程组: 子线程组, 父线程组: root线程组
  5. 批量中断组内线程
  6. 线程A执行结束
  7. 线程B执行结束
  8. 线程C执行结束
  9. 线程D执行结束
  10. 复制代码

本文只是对Java中的ThreadGroup类进行了简单的介绍和使用示范,更多线程组的操作可以查看JDK API。

参考:

https://www.cnblogs.com/xrq730/p/4856072.html

https://www.cnblogs.com/barrywxx/p/9976417.html

最后,小编这里有一些架构资料可以分享给大家!

请加772300343领取!

谢谢关注!

浅析Java中线程组(ThreadGroup类)的更多相关文章

  1. JDK中线程组ThreadGroup

    如果线程有100条...分散的不好管理... 线程同样可以分组ThreadGroup类. 线程组表示一个线程的集合.此外,线程组也可以包含其他线程组.线程组构成一棵树,在树中,除了初始线程组外,每个线 ...

  2. java 多线程 线程组ThreadGroup;多线程的异常处理。interrupt批量停止组内线程;线程组异常处理

    1,线程组定义: 线程组存在的意义,首要原因是安全.java默认创建的线程都是属于系统线程组,而同一个线程组的线程是可以相互修改对方的数据的.但如果在不同的线程组中,那么就不能"跨线程组&q ...

  3. 线程组ThreadGroup分析详解 多线程中篇(三)

    线程组,顾名思义,就是线程的组,逻辑类似项目组,用于管理项目成员,线程组就是用来管理线程. 每个线程都会有一个线程组,如果没有设置将会有些默认的初始化设置 而在java中线程组则是使用类ThreadG ...

  4. “全栈2019”Java多线程第十三章:线程组ThreadGroup详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  5. 线程组ThreadGroup

      ThreadGroup线程组表示一个线程的集合.此外,线程组也可以包含其他线程组. 线程组构成一棵树,在树中,除了初始线程组外,每个线程组都有一个父线程组. 允许线程访问有关自己的线程组的信息,但 ...

  6. 多线程(三) java中线程的简单使用

    java中,启动线程通常是通过Thread或其子类通过调用start()方法启动. 常见使用线程有两种:实现Runnable接口和继承Thread.而继承Thread亦或使用TimerTask其底层依 ...

  7. 沉淀再出发:java中线程池解析

    沉淀再出发:java中线程池解析 一.前言 在多线程执行的环境之中,如果线程执行的时间短但是启动的线程又非常多,线程运转的时间基本上浪费在了创建和销毁上面,因此有没有一种方式能够让一个线程执行完自己的 ...

  8. 浅析Java中的final关键字

    浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...

  9. 浅析Java中的访问权限控制

    浅析Java中的访问权限控制 今天我们来一起了解一下Java语言中的访问权限控制.在讨论访问权限控制之前,先来讨论一下为何需要访问权限控制.考虑两个场景: 场景1:工程师A编写了一个类ClassA,但 ...

随机推荐

  1. xml解析-jaxp遍历结点

    jaxp遍历结点 把xml中所有的结点都打印出来 // 遍历结点把所有元素名称打印出来 / 1.创建解析器工厂 * 2.根据解析器工厂创建解析器 * 3.解析xml返回document * * 4.得 ...

  2. MAC TXT文本

    Mac系统下.txt格式的纯文本怎么保存? 作者:佚名 字体:[增加 减小] 来源:互联网 时间:06-02 14:29:23 我要评论 Mac系统下.txt格式的纯文本怎么保存?.txt是个用途广泛 ...

  3. 查看sybase IQ的执行计划

    在性能调优工作中,首要的事情是找出性能瓶颈.而针对数据库应用,由于商用数据库对上层应用来说是个黑盒,所以往往需要借助数据库的一些接口或工具来了解数据库的具体行为,并结合相关知识和业务进行调测.    ...

  4. Java学习笔记(2)--- 对象和类入门,java包,this 和 super区别

    1.对象和类(Object and class): 一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作. 面对对象编程是java非常重要的一部分,作者本身之前学过c ...

  5. Jenkins之插件Publish HTML reports的使用

    前提: 下载插件HTML Publisher plugin 一.安装 安装好HTML Publisher plugin之后,会在新建或者编辑项目时,在[增加构建后操作步骤]出现[Publish HTM ...

  6. C# WF 第12节 Timer控件

    本节内容: 1:Timer控件的简介 2:实例1  : 不停的弹出,恶意exe 3:实例2: :流水灯 4:实例3:给流水灯加上计时器和在规定的时间进行播放音乐 1:Timer控件的简介 2:实例1 ...

  7. day66_10_10,vue项目环境搭建

    一.下载. 首先去官网查看网址. 下载vue环境之前需要先下载node,使用应用商城npm下载,可以将其下载源改成cnpm: """ node ~~ python:nod ...

  8. 《阿里B2B技术架构演进详解》----阅读

    B2B(Business To Business)是指一个市场的领域的一种,是企业对企业之间的营销关系.先来总结一下阿里B2B共分为三个阶段: 第一阶段,建立信息网站提供信息和营销服务平台,让买家更加 ...

  9. Python __slots__

    Python 类的特殊变量:__slots__ 使用 __slots__ 后,类中 __weakref__ 和 __dict__ 消失,同时阻止动态属性绑定 由于 __dict__ 记录着类中所有的属 ...

  10. 树莓派开机主动发送自己的局域网ip/外网ip到你的微信

    开机时,树莓派主动发送自己的内网ip以及公网ip到你的微信上,这样就能方便地使用ssh或VNC. 操作步骤 下载目录下的 boot_getIP_send_Wechat.py 到你的 Raspberry ...