ThreadGroup API介绍
ThreadGroup API介绍
TreadGroup其实是在1.5之前用的比较多,在没有线程池API前都使用TreadGroupApi来管理线程池。虽然现在有线程池API来供大家使用,但是如果在平时开发中只想启用三五个线程,那么可以选择使用TreadGroup来管理线程。
我们找到ThreadGroup来看一下:

线程组表示一组线程。此外,线程组还可以包括其他线程组。线程组形成一个树,其中除了初始线程组外,每个线程组都有一个父线程组。
允许线程访问关于其自己线程组的信息,但不允许访问关于其线程组的父线程组或任何其他线程组的信息。
那么,允许线程访问关于其自己线程组的信息的信息都是什么呢?我们接下来看一下:
首先创建一个threadgroup
public class ThreadGroupCreate {
public static void main(String[] args) {
// 1. use the name
ThreadGroup tg1 = new ThreadGroup("TG1");
Thread t1 = new Thread(tg1, () -> {
while (true) {
try {
Thread.sleep(10_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "T1");
t1.start();
System.out.println("t1's thread group name = " + t1.getThreadGroup().getName());// TG1
//todo 2. use the parent and group name
}
}
运行效果如下:

打印一下当前threadgroup的名字和他父级的名字:
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
System.out.println(threadGroup.getName());
System.out.println(threadGroup.getParent());
运行效果如下:

可以看到他的线程组是TG1,他的夫级线程组是main,并且main线程的优先级很高是10。
接下来我们给创建另一个线程组,他的夫级线程组TG1:
//2. use the parent and group name
ThreadGroup tg2 = new ThreadGroup(tg1, "TG2");
System.out.println("tg2's name = " + tg2.getName());
System.out.println("tg2's parent name = " + tg2.getParent().getName());
运行效果如下:

线程组两种创建方式就ok了,我们再来验证一下:允许线程访问关于其自己线程组的信息,但不允许访问关于其线程组的父线程组或任何其他线程组的信息。
//TG2 访问TG1
ThreadGroup tg2 = new ThreadGroup(tg1, "TG2");
Thread t2 = new Thread(tg2,()->{
System.out.println("tg2's parent threadgroup is"+tg2.getName());
});
t2.start();
// TG3与TG1为同一个父ThreadGroup-main
// 测试TG3能否访问TG1的一些信息
ThreadGroup tg3 = new ThreadGroup("TG3");
Thread t3 = new Thread(tg3, () -> {
System.out.println(">>>>" + t1.getName());// TG1
Thread[] threads = new Thread[tg1.activeCount()];
tg1.enumerate(threads);
Stream.of(threads).forEach(System.out::println);// Thread[T1,5,TG1]
}, "T3");
t3.start();
运行效果如下:
可以看到其实是可以访问的,可能是官方文档有问题,也有可能是我翻译的有问题。。。
接下来学习几个ThreadGroup的常用方法:
activeCount()

返回此线程组及其子组中活动线程的评估数量。这里注意是评估数量,因为可能获取的时候,某个线程消亡了或者正在被添加。
public class ThreadGroupAPI {
public static void main(String[] args) {
ThreadGroup tg1 = new ThreadGroup("TG1");
Thread t1 = new Thread(tg1, () -> {
while (true) {
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}, "T1");
/*tg1.setDaemon(true);*/
t1.start();
ThreadGroup tg2 = new ThreadGroup(tg1, "TG2");
Thread t2 = new Thread(tg2, () -> {
while (true) {
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}, "T2");
t2.start();
System.out.println("tg1 active count is " + tg1.activeCount());
}
}
运行效果如下:

activeGroupCount()

返回此线程组及其子组中活动组的评估数量。
System.out.println(tg1.activeGroupCount());
运行效果如下:

checkAccess()

确定当前运行的线程是否具有修改此线程组的权限。
代码如下:
tg1.checkAccess();
运行效果如下:

没抛出异常代表有权限修改线程组。
destroy()

销毁这个线程组及其所有子组。destroy前需要确定线程组里没有活跃的线程。如果线程组不为空或线程组已被销毁将抛出IllegalThreadStateException
代码如下:
tg1.destroy();
运行效果如下:

因为我们线程里有while,所以是活跃的线程,这里就抛出异常了。
enumerate(Thread[] list)

将此线程组及其子组中的每个活动线程复制到指定的数组中。
代码如下:
Thread[] ts1 = new Thread[tg1.activeCount()];
tg1.enumerate(ts1);
System.out.println(Arrays.toString(ts1));
运行效果如下:

enumerate(Thread[] list, boolean recurse)

将此线程组中的每个活动线程复制到指定数组中。
代码如下:
Thread[] ts2 = new Thread[tg1.activeCount()];
tg1.enumerate(ts2, false);
System.out.println(Arrays.toString(ts2));
运行效果如下:


如果为真,则递归枚举此线程组的所有子组。那么我们使用false试试:
ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup();
Thread[] ts3 = new Thread[mainThreadGroup.activeCount()];
mainThreadGroup.enumerate(ts3, false);
System.out.println(Arrays.toString(ts3));
运行效果如下:

interrupt()

中断此线程组中的所有线程。
代码如下:
tg1.interrupt();
运行效果如下:

setDaemon(boolean daemon)

守护进程——如果为真,则将此线程组标记为守护线程组;否则,将此线程组标记为normal。
ThreadGroup tg1 = new ThreadGroup("TG1");
Thread t1 = new Thread(tg1, () -> {
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T1");
tg1.setDaemon(true);
t1.start();
Thread.sleep(2_000);
System.out.println(tg1.isDestroyed());
运行效果如下:

注释tg1.setDaemon(true);试一下:

手动销毁一下:
ThreadGroup tg1 = new ThreadGroup("TG1");
Thread t1 = new Thread(tg1, () -> {
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T1");
//tg1.setDaemon(true);
t1.start();
Thread.sleep(2_000);
System.out.println(tg1.isDestroyed());
tg1.destroy();
System.out.println(tg1.isDestroyed());
运行效果如下:

这篇随笔是我周六没吃早饭没吃午饭弄到下午4点38才弄完的,内容虽然你不多但是改来改去,时间也就慢慢过去了,中间多少次想休息一会吃个饭再继续弄,但是还是想弄完了再好好吃饭,也许这样下去永远都胖不起来吧。。。哎精神粮食充实啊~

浙公网安备 33010602011771号