线程组ThreadGroup标识一组线程的集合,一旦一个线程归属到一个线程组中,就不能更换其所在的线程组。
使用线程组好处:方便统一管理,线程组合一进行复制,快读定位到一个线程,统一进行一场设置等。
ThreadGroup并不属于java并发包中的内容,它是java.lang中的内容。
基本方法:
1.获取当前线程组名:
Thread.currentThread().getThreadGroup().getName();
在main方法中输出main
2.将线程放入到一个线程组中去
ThreadGroup tg = new ThreadGroup("My Group");
MyThread2 thrd = new MyThread2(tg, "MyThread #1");
MyThread2 thrd2 = new MyThread2(tg, "MyThread #2");
MyThread2 thrd3 = new MyThread2(tg, "MyThread #3");
其中Thread中和ThreadGroup相关的构造函数:
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
init(group, target, name, stackSize);
}
它们最终都是调用同一个函数:
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
//安全检查
if (security != null) {
g = security.getThreadGroup();
}
//设置线程组
if (g == null) {
g = parent.getThreadGroup();
}
}
//检查可达性
g.checkAccess();
//是否有权限访问
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
//往线程组添加线程但未启动
g.addUnstarted();
this.group = g;
this.daemon = parent.isDaemon();//是否守护线程
this.priority = parent.getPriority();//优先级
this.name = name.toCharArray();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext = AccessController.getContext();
this.target = target;
setPriority(priority);
if (parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
this.stackSize = stackSize;
tid = nextThreadID();
this.me = this;
}
3、复制线程组:
Thread thrds[] = new Thread[tg.activeCount()];
tg.enumerate(thrds);
这里的activeCount很明显就是取得活动的线程,注意。默认情况 下,连同其子线程组也会进行复制。
4、未捕获异常处理
ThreadGroup中有一个uncaughtException()方法。当线程组中某个线程发生Unchecked exception异常时,由执行环境调用此方法进行相关处理,如果有必要,可以重新定义此方法
统一异常处理:
public class ThreadGroupExec {
public static void main(String[] args) {
ThreadGroup threadGroup1 = new ThreadGroup("group1"){
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println(t.getName() + ": " + e.getMessage());
}
};
// 这是匿名类写法
Thread thread1 =
// 这个线程是threadGroup1的一员
new Thread(threadGroup1, new Runnable() {
@Override
public void run() {
// 抛出unchecked异常
throw new RuntimeException("测试异常");
}
});
thread1.start();
}
}
查看构造函数:
public class ThreadGroup implements Thread.UncaughtExceptionHandler {
private final ThreadGroup parent;//父亲ThreadGroup
String name;//ThreadGroupr 的名称
int maxPriority;//线程最大优先级
boolean destroyed;//是否被销毁
boolean daemon;//是否守护线程
boolean vmAllowSuspension;//是否可以中断
int nUnstartedThreads = 0;//还未启动的线程
int nthreads;//ThreadGroup中线程数目
Thread threads[];//ThreadGroup中的线程
int ngroups;//线程组数目
ThreadGroup groups[];//线程组数组
参考:
https://blog.csdn.net/evankaka/article/details/51627380
http://blog.csdn.net/edward\_qing\_lee/article/details/8767612