线程组

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

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

线程关联线程组: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出来,没有指定线程组,那么自动归到当前线程所属的线程组中,也就是隐式地在一个线程组中添加了一个子线程组。

 这里线程组的enumerate是用来拷贝线程组,或者线程数组到指定的数组中的,有两个重载方法,因为线程组没有显示get返回线程组数据或者线程数据给你,只有这个方法可以拷贝


线程组内加线程组





以上代码演示了在指定线程组内再加子线程组,可以无限延伸下去





根线程组

看一下根线程组:

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 codethis.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。


递归与非递归获取组内对象


看到在调用emumerate方法的时候可以传入第二个参数就是是否递归下去



java 多线程 24 : 线程组的更多相关文章

  1. 【Java基础】Java多线程之线程组和线程池

    在上一篇文章中,讲述了线程的基本概念和用法,这里将继续讲述线程组和线程池的一些东西. 线程组:java.lang.ThreadGroup 1. 线程组的介绍 线程组表示一个线程的集合.此外,线程组也可 ...

  2. java多线程之线程组与线程池

    看这篇文章:http://blog.csdn.net/zen99t/article/details/50909099

  3. Java多线程父子线程关系 多线程中篇(六)

    有的时候对于Java多线程,我们会听到“父线程.子线程”的概念. 严格的说,Java中不存在实质上的父子关系 没有方法可以获取一个线程的父线程,也没有方法可以获取一个线程所有的子线程 子线程的消亡与父 ...

  4. JAVA多线程之线程间的通信方式

    (转发) 收藏 记 周日,北京的天阳光明媚,9月,北京的秋格外肃穆透彻,望望窗外的湛蓝的天,心似透过栏杆,沐浴在这透亮清澈的蓝天里,那朵朵白云如同一朵棉絮,心意畅想....思绪外扬, 鱼和熊掌不可兼得 ...

  5. java多线程与线程间通信

    转自(http://blog.csdn.net/jerrying0203/article/details/45563947) 本文学习并总结java多线程与线程间通信的原理和方法,内容涉及java线程 ...

  6. Java多线程之线程其他类

    Java多线程之线程其他类 实际编码中除了前面讲到的常用的类之外,还有几个其他类也有可能用得到,这里来统一整理一下: 1,Callable接口和Future接口 JDK1.5以后提供了上面这2个接口, ...

  7. Java多线程之线程的通信

    Java多线程之线程的通信 在总结多线程通信前先介绍一个概念:锁池.线程因为未拿到锁标记而发生的阻塞不同于前面五个基本状态中的阻塞,称为锁池.每个对象都有自己的锁池的空间,用于放置等待运行的线程.这些 ...

  8. Java多线程之线程的同步

    Java多线程之线程的同步 实际开发中我们也经常提到说线程安全问题,那么什么是线程安全问题呢? 线程不安全就是说在多线程编程中出现了错误情况,由于系统的线程调度具有一定的随机性,当使用多个线程来访问同 ...

  9. Java多线程之线程的控制

    Java多线程之线程的控制 线程中的7 种非常重要的状态:  初始New.可运行Runnable.运行Running.阻塞Blocked.锁池lock_pool.等待队列wait_pool.结束Dea ...

  10. 关于Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇高质量的博文)

    Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇质量高的博文) 前言:在学习多线程时,遇到了一些问题,这里我将这些问题都分享出来,同时也分享了几篇其他博客主的博客,并且将我个人的理解也分享 ...

随机推荐

  1. webpack window 添加第三方库

    有的时候还想来点jquery,moment,undersocre之类的库,webpack可以非常容易的做到这一点,有谣言说Bower即将停止开发了, 作者推荐都使用npm来管理依赖.那么我们现在安装在 ...

  2. svn搭建本地服务端

    使用VisualSVN Server来完成,下载地址:https://www.visualsvn.com/server/download/ 我安装的版本是3.3.1,安装的时候选择了标准版本,另外一个 ...

  3. oracle三大范式(转载)

    标准化表示从你的数据存储中移去数据冗余 (redundancy)的过程.如果数据库设计达到了完全的标准化,则把所有的表通过关键字连接在一起时,不会出现任何数据的复本 (repetition).标准化的 ...

  4. 虚拟化—Docker解决方案

    What is Docker? Docker is an open-source project to easily create lightweight, portable, self-suffic ...

  5. top 学习

    通常top命令是会持续运行而不终止的. 要在脚本里用,需要添加一些选项参数,尤其是-b.例如:top -b -n 2 -d 3 >/tmp/log -b表示批处理模式(Batch mode),以 ...

  6. Dapper MySql DateTime 异常

    实体类 字段类型 DateTime? ,MySQL数据库中字段类型 datetime NULL , 使用dapper扩展读取,报异常:Error Parse column: ** - Object. ...

  7. 由苹果的低级Bug想到的

    2014年2月22日,在这个“这么二”的日子里,苹果公司推送了 iOS 7.0.6(版本号11B651)修复了 SSL 连接验证的一个 bug.官方网页在这里:http://support.apple ...

  8. 【SDOI2014】【BZOJ3529】数表

    Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼.1 < =j < =m)的数值为 能同一时候整除i和j的全部自然数之和.给定a,计算数表中不 ...

  9. python selenium 常见问题列表

    python selenium webdriver 常见问题FAQ 另一个FAQ: https://code.google.com/p/selenium/wiki/FrequentlyAskedQue ...

  10. Openssl aes加解密例程 更进一步

    原文链接: http://blog.csdn.net/itmes/article/details/7718427 前面我们用openssl的aes256对称加密算法对16个字节的内存块进行了的加解密运 ...