线程组

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

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

线程关联线程组: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。

Java多线程16:线程组的更多相关文章

  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多线程之线程的生命周期 一.前言 当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态.在线程的生命周期中,它要经过新建(New).就绪(Runnable).运行(R ...

  7. Java多线程| 01 | 线程概述

    Java多线程| 01 | 线程概述 线程相关概念 进程与线程 进程:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是操作系统进行资源分配与调度的基本单位.可以把进程简单的理解 ...

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

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

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

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

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

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

随机推荐

  1. qweb

    qweb 是 odoo的模板系统, 在 odoo系统中, 它有不同的用途和实现, 一个是 web client 的 widget 的渲染引擎, 它是通过 javascript实现的,也是 最早引入到 ...

  2. Linux C++ 开发常用工具,常用指令工作手册

    vim常用: :set nu显示行数 :set mouse=a 鼠标滑动屏幕,:set ic :set noic 忽略不忽略大小写 /word_to_search\c \c表示忽略大小写 c小写忽略, ...

  3. Web程序的运行原理及流程(一)

    自己做Web程序的开发也有两年多了 从最开始跟风学框架  到第一用上框架的欣喜若狂 我相信每个程序员都是这样过来的 在大学学习一门语言 学会后往往很想做一个实际的项目出来  我当时第一次做WEB项目看 ...

  4. [python]自动化将markdown文件转成html文件

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  5. angularjs 分页精华代码

    //pageinfo $scope.pageSize=10;$scope.currentType={{ current_type }};$scope.currentPage={{ json_encod ...

  6. CentOS6.5 (64bit) 光盘内部FTP源

    一.启动系统,用ISO镜像挂载[root@yum ~]# mkdir -p /mnt/cdrom01[root@yum ~]# mkdir -p /mnt/cdrom02 [root@yum ~]# ...

  7. centos 如何清理/dev/vda1系统盘

    df-h检查一台服务器磁盘使用空间,发现磁盘已经使用了100% 思路是: 1.cd /usr 2.du -sh * 看哪个目录占用空间大 3.重复前两步,根据实际情况删除或者移走 4.日志的话可以运行 ...

  8. Mac 系统下的环境变量

    1.查看电脑环境变量   -->echo $PATH 2. 新建环境变量   sudo vim ~/.bash_profile  输入密码 3. 按 I ,编辑新的环境变量地址,保存 退出 :w ...

  9. rsync+inotify实现远程数据备份

    一.rsync的基本介绍 1.  什么是rsync Rsync是一款开源的.快速的.多功能的.可以实现增量的本地货远程数据镜像同步备份的优秀工具,Rsync使用与unix,linux,windows等 ...

  10. java 堆栈的区别(转百度)

    转:http://zhidao.baidu.com/link?url=Y1XnuCnTiw6BsUoW85MWSx_x7k0QAS39kz4dTy9ngkMkZjvlSEHVfdflOGVWs6TcH ...