ThreadGroup简介
顾名思义,线程组是多个线程的集合,可以对一批线程或线程组进行统一管理,比如中断interrupt(),destroy()。另外可以准确的定位到某个线程和进行统一的异常捕获。一个线程组中可以有线程,也可以有线程组,所以线程组的结构有点类似于树,如下所示
下面通过代码来看,线程组的树形结构
public static void main(String[] args) {
ThreadGroup tg = new ThreadGroup("tg");
while(tg.getParent() != null){
tg = tg.getParent();
}
tg.list();
}
运行结果如下:
java.lang.ThreadGroup[name=system,maxpri=10]
Thread[Reference Handler,10,system]
Thread[Finalizer,8,system]
Thread[Signal Dispatcher,9,system]
Thread[Attach Listener,5,system]
java.lang.ThreadGroup[name=main,maxpri=10]
Thread[main,5,main]
Thread[Monitor Ctrl-Break,5,main]
java.lang.ThreadGroup[name=tg,maxpri=10]
ThreadGroup属性与构造方法
private final ThreadGroup parent; // 父线程组
String name; // 线程组名称
int maxPriority; // 最大优先级,线程组中的线程优先级不能高于此
boolean destroyed; // 是否被销毁
boolean daemon; // 是否守护线程
boolean vmAllowSuspension; //是否可以中断
int nUnstartedThreads = 0; // 未启动的线程
int nthreads; // ThreadGroup中线程数目
Thread threads[]; // ThreadGroup中的线程
int ngroups; // 线程组数目
ThreadGroup groups[]; // 线程组数组
// 最顶层线程组
private ThreadGroup() {
this.name = "system";
this.maxPriority = Thread.MAX_PRIORITY;
this.parent = null;
}
// 如果没有指定线程组,默认以当前线程所在线程组为父线程组
public ThreadGroup(String name) {
this(Thread.currentThread().getThreadGroup(), name);
}
// 指定父线程组
public ThreadGroup(ThreadGroup parent, String name) {
// checkParentAccess检查当前线程是否有权限修改parent线程组
this(checkParentAccess(parent), parent, 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倍扩容
}
ThreadGroup Api如下(过时方法未列出)
int activeCount() //返回此线程组及其子组中活动线程数的估计
int activeGroupCount() //返回此线程组及其子组中活动组数的估计
void checkAccess() //确定当前运行的线程是否有权限修改此线程组
void destroy() //销毁此线程组及其所有子组
int enumerate(Thread[] list) //将此线程组及其子组中的每个活动线程复制到指定的数组中
int enumerate(Thread[] list, boolean recurse) //将此线程组中的每个活动线程复制到指定的数组中
int getMaxPriority() //返回此线程组的最大优先级
String getName() //返回此线程组的名称
ThreadGroup getParent() //返回此线程组的父级
void interrupt() //中断此线程组中的所有线程
boolean isDaemon() //测试此线程组是否是守护线程组
boolean isDestroyed() //测试此线程组是否已被破坏
void list() //将有关此线程组的信息打印到标准输出。
boolean parentOf(ThreadGroup g) //测试此线程组是线程组参数还是其祖先线程组之一
void setDaemon(boolean daemon) //更改此线程组的守护程序状态
void setMaxPriority(int pri) //设置组的最大优先级
String toString() //返回此Thread组的字符串表示形式
void uncaughtException(Thread t, Throwable e) //当该线程组中的线程由于未捕获的异常而停止时,由Java虚拟机调用,并且该线程没有特定的Thread.UncaughtExceptionHandler设置
线程组的异常处理
ThreadGroup group = new ThreadGroup("group") {
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
System.out.println(thread.getName() +":"+ throwable.getMessage());
}
};
Thread thread = new Thread(group, new Runnable() {
@Override
public void run() {
throw new RuntimeException("线程内部抛出异常");
}
});
thread.start();
// 上述group如果眉头重写uncaughtException,则直接往外抛出,
// 重写后抛出异常则会调用uncaughtException进行处理,前提当然是thread是group下的线程。
ThreadGroup group = new ThreadGroup("group") {
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
System.out.println("enter ThreadGroup uncaughtException: " + thread.getName() + "#" + throwable.getMessage());
}
};
Thread thread0 = new Thread(group, new Runnable() {
@Override
public void run() {
throw new RuntimeException("线程内部抛异常0");
}
});
Thread thread1 = new Thread(group, new Runnable() {
@Override
public void run() {
throw new RuntimeException("线程内部抛异常1");
}
});
thread0.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("enter UncaughtExceptionHandler uncaughtException: " + t.getName() + "#" + e.getMessage());
}
});
thread0.start();
thread1.start();
// 线程内部抛出异常捕获优先级顺序:UncaughtExceptionHandler.uncaughtException > ThreadGroup.uncaughtException