一、线程组概述
线程组ThreadGroup表示一组线程的集合,一旦一个线程归属到一个线程组之中后,就不能再更换其所在的线程组。Java使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。
线程组的作用:方便统一管理,线程组可以进行复制,快速定位到一个线程,统一进行异常设置等。ThreadGroup它其实并不属于Java并发包中的内容,它是java.lang中的内容。
二、源码分析
2.1 继承关系
public class ThreadGroup implements Thread.UncaughtExceptionHandler {
ThreadGroup中有一个uncaughtException()方法。当线程组中某个线程发生Unchecked exception异常时,由执行环境调用此方法进行相关处理,如果有必要,可以重新定义此方法
2.2 属性
private final ThreadGroup parent; // 父线程组
String name;// 线程组名称
int maxPriority;// 线程组优先级
boolean destroyed;//是否已经被销毁
boolean daemon; // 守护线程
boolean vmAllowSuspension;// 供VM使用
int nUnstartedThreads = 0;// 线程组中未启动的线程
int nthreads;// 线程数量
Thread threads[]; // 线程
int ngroups; // 线程组数量
ThreadGroup groups[]; // 线程组
2.3 构造方法
2.3.1私有的默认构造方法
/**
* 创建系统线程组,不在任何线程组中的空线程组
*
*/
private ThreadGroup() { // called from C code
this.name = "system";
this.maxPriority = Thread.MAX_PRIORITY;
this.parent = null;
}
2.3.2带一个参数线程组名称name的构造方法
/**
*创建带一个参数线程组名称name的构造方法,
* 底层调用的是带俩参数的构造方法
* @param name the name of the new thread group.
* @exception SecurityException if the current thread cannot create a
* thread in the specified thread group.
* @see java.lang.ThreadGroup#checkAccess()
* @since JDK1.0
*/
public ThreadGroup(String name) {
this(Thread.currentThread().getThreadGroup(), name);
}
2.3.3创建带两个参数父类线程组、线程组名称name的构造方法
/**
* 创建带两个参数父类线程组、线程组名称name的构造方法
* @param parent the parent thread group.
* @param name the name of the new thread group.
* @exception NullPointerException if the thread group argument is
* <code>null</code>.
* @exception SecurityException if the current thread cannot create a
* thread in the specified thread group.
* @see java.lang.SecurityException
* @see java.lang.ThreadGroup#checkAccess()
* @since JDK1.0
*/
public ThreadGroup(ThreadGroup parent, String name) {
this(checkParentAccess(parent), parent, name);
}
2.3.3创建带三个参数父类线程组、线程组名称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);// 把当前线程组添加到父线程组
}
2.4 普通方法
2.4.1 获取线程组中的信息
public int activeCount(); // 获得当前线程组中线程数目, 包括可运行和不可运行的
public int activeGroupCount(); //获得当前线程组中活动的子线程组的数目
public int enumerate(Thread list[]); //列举当前线程组中的线程
public int enumerate(ThreadGroup list[]); //列举当前线程组中的子线程组
public final int getMaxPriority(); //获得当前线程组中最大优先级
public final String getName(); //获得当前线程组的名字
public final ThreadGroup getParent(); //获得当前线程组的父线程组
public boolean parentOf(ThreadGroup g); //判断当前线程组是否为指定线程的父线程
public boolean isDaemon(); //判断当前线程组中是否有监护线程
public void list(); //列出当前线程组中所有线程和子线程名
2.4.2对线程组操作
public final void resume(); //使被挂起的当前组内的线程恢复到可运行状态
public final void setDaemon (boolean daemon); //指定一个线程为当前线程组的监护线程
public final void setMaxPriority(int pri); //设置当前线程组允许的最大优先级
public final void stop();//终止当前线程组中所有线程
public final void suspend(); //挂起当前线程组中所有线程
public String toStrinng(); //将当前线程组转换为String类的对象
三 、使用例子
3.1 例子1
package cn.itcast_05;
public class MyRunnable implements Runnable {
@Override
public void run() {
for(int x=0;x<10;x++){
System.out.println(Thread.currentThread().getName()+":"+x);
}
}
}
package cn.itcast_05;
/**
* 线程组:
* @author jack
*
*/
public class ThreadGroupDemo {
public static void main(String[] args) {
MyRunnable my=new MyRunnable();
Thread t1=new Thread(my,"赵云");
Thread t2=new Thread(my,"关羽");
//这样我不知道他们属于哪个组,我想知道怎么办
String t1Group=t1.getThreadGroup().getName();
String t2Group=t2.getThreadGroup().getName();
System.out.println("t1Group:"+t1Group);
System.out.println("t2Group:"+t2Group);
//通过结果我们知道线程默认情况下属于main线程 组
//通过下面的测试看到,在默认情况下,所有的线程都属于一个组
System.out.println("Main线程的线程组:"+Thread.currentThread().getThreadGroup().getName());
t1.start();
t2.start();
ThreadGroup t=t1.getThreadGroup();
}
}
运行结果:
t1Group:main
t2Group:main
Main线程的线程组:main
赵云:0
关羽:0
关羽:1
关羽:2
关羽:3
关羽:4
关羽:5
关羽:6
关羽:7
关羽:8
关羽:9
赵云:1
赵云:2
赵云:3
赵云:4
赵云:5
赵云:6
赵云:7
赵云:8
赵云:9