我的原则:先会用再说,内部慢慢来。
学以致用,根据场景学源码
一、前言
1.1 架构
1.2 ThreadGroup 能干嘛?
- 能用来操作group下面的所有线程,比如全部打断 interrupt
- 可以进行链路监控,例如监控某个 group 下面,当前存在多少活跃线程数目。
- 统一捕获该group下线程抛出的异常。
1.3 ThreadGroup 常用的方法
方法 | 描述 |
---|---|
int activeCount() | 查看组内部 thread 活跃数量(包括子group) |
int activeGroupCount() | 查看组内部 group 活跃数量(包括子group) |
void list() | 打印出group下的所有线程信息(包括子group) |
void destroy() | 摧毁线程(包括子group) |
boolean isDestroyed() | 查看该 group 有没有被摧毁 |
int enumerate(Thread[] list) | copy 某个group 下面的活跃 thread |
ThreadGroup getParent() | 找爸爸 |
void interrupt() | 打断这个 group 下面的所有 thread |
boolean isDaemon() | 看下是否是幽灵线程 |
void setDaemon(boolean daemon) | 设置幽灵线程 |
二、实战
2.1 实战一 :验证 Count
- 本demo验证了activeCount、activeGroupCount、list、getParent、interrupt 等一系列方法
- 代码流程如下:
- 创建 group1
- group1 先创建thread1,2,3 ,由于没start,activeCount得到的的结果是 0
- thread1,2,3 启动起来(暂时不关闭),activeCount得到的的结果是 3
- 插入 thread4, 启动起来,activeCount得到的的结果是 4
- thread4 线程跑完,activeCount得到的的结果是 3
- 创建group2(传入 group1)
- 打印出 group2,group1,还有顶级 main 的list信息
- interrupt 测试打断,诶,虽然main线程跑到最后了,打那是发现scanner.nextLine() 由于内部的死循环while,无法被打断。
public static void testGroupListAndSize() throws Exception {
ThreadGroup group1 = new ThreadGroup("Group1");
Thread t1 = new Thread(group1, () -> {
try {
Scanner sc = new Scanner(System.in);
System.out.println("点击任意键唤醒线程 ...");
sc.nextLine();
} catch (Exception e) {
System.out.println("t1 被打断啦 ...");
}
});
Thread t2 = new Thread(group1, () -> {
try {
Scanner sc = new Scanner(System.in);
System.out.println("点击任意键唤醒线程 ...");
sc.nextLine();
} catch (Exception e) {
System.out.println("t2 被打断啦 ...");
}
});
Thread t3 = new Thread(group1, () -> {
try {
Scanner sc = new Scanner(System.in);
System.out.println("点击任意键唤醒线程 ...");
sc.nextLine();
} catch (Exception e) {
System.out.println("t3 被打断啦 ...");
}
});
/*
1. 线程未启动,未注册到 group 里面去
*/
group1.list();
System.out.println("group1.size -> " + group1.activeCount());
Thread.sleep(1000);
System.out.println("----");
/*
2. 启动线程
*/
t1.start();
t2.start();
t3.start();
Thread.sleep(1000);
group1.list();
System.out.println("group1.size -> " + group1.activeCount());
System.out.println("----");
System.out.println("==== 启动 thread4,验证 activeCount 含义(只返回活跃数量) ====");
/*
启动 thread4,验证 activeCount 含义(只返回活跃数量)
*/
Thread t4 = new Thread(group1, () -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("t4 被打断啦 ...");
}
});
t4.start();
group1.list();
System.out.println("group1.size -> " + group1.activeCount());
System.out.println("----");
Thread.sleep(2000);
System.out.println(" === 2s 后 ,t4 已经down ===");
group1.list();
System.out.println("group1.size -> " + group1.activeCount());
System.out.println("----");
Thread.sleep(1000);
System.out.println("==== 创建子group ====");
ThreadGroup group2 = new ThreadGroup(group1,"Group2");
Thread t21 = new Thread(group2, () -> {
try {
Scanner sc = new Scanner(System.in);
System.out.println("点击任意键唤醒线程 ...");
sc.nextLine();
} catch (Exception e) {
System.out.println("t21 被打断啦 ...");
}
});
t21.start();
Thread.sleep(1000);
System.out.println("遍历下 group1 ,观察是否加入了...");
group1.list();
System.out.println("遍历下 group2 ...");
group2.list();
System.out.println("最后遍历下最牛逼的 group-main ...");
Thread.currentThread().getThreadGroup().list();
Thread.sleep(1000);
/*
interrupt
*/
System.out.println("=== 最后打断全部线程 ===");
// group1.destroy();
group1.interrupt();
/*
sc.nextLine(); 太牛逼了,里面有死循环,听不到外面的打断
*/
System.out.println("main thread end ...");
}
- 输出:
java.lang.ThreadGroup[name=Group1,maxpri=10]
group1.size -> 0
---