概述

看源代码中总免不了一些不是太熟悉的知识,本节过一下线程组的相关知识,以便后续快速翻阅。

功能

事出必有因,线程组的出现自然也有一定的原因,那就是方便线程的管理,线程组是树状的结构,整体如下: 简单说明一下,每一个线程都会隶属于一个线程组,线程组也都会有父线程组, 依次向上查找可以找到system线程组。

  • jvm创建的system线程组主要是用来管理jvm系统任务的线程组,如垃圾回收。
  • system线程组的直属线程组是main线程组,该线程组至少包含一个main线程,用于执行main方法。
  • main线程组的子线程组就是应用程序级别的线程组,这些线程组一般是用户创建的。

    示例

    上面简要的介绍了一下线程组的整体结构,接下来代码演示一下线程组的一些用法

构造

1
2
3
4
5
6
7
public ThreadGroup(String name) {
this(Thread.currentThread().getThreadGroup(), name);
}

public ThreadGroup(ThreadGroup parent, String name) {
this(checkParentAccess(parent), parent, name);
}

上面是threadgroup的两个构造函数,由上面的两个构造函数可以看到,我们可以仅指定线程组的名称,这样默许创建的线程组隶属于当前线程所在的线程组。 当然我们也可以明确的指定所创建的线程组的父线程组,这样所创建的线程组的父线程组即是我们在构造函数中指定的线程组

线程组信息查看

这里主要涉及到线程组相关的API,暂时可以先忽略,待需要的时候查看即可

线程管理

下面以终止线程组中所有的线程的个数为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class HelloWorld {

public static void main(String[] args) throws InterruptedException {
ThreadGroup tg = new ThreadGroup("aaa");
Thread t1 = new Mythread(tg, "t1");
Thread t2 = new Mythread(tg, "t2");
t1.start();
t2.start();
Thread.sleep(10000);
System.out.println("before interrupt" + tg.activeCount());
tg.interrupt();
// 获取当前线程组至下所有的活动的线程的个数,该方法返回的是大约的数量
System.out.println("after interrupt" + tg.activeCount());

}
private static class Mythread extends Thread {

public Mythread(ThreadGroup tg, String name) {
super(tg, name);
}

@Override
public void run() {
synchronized ("a") {
try {
System.out.println("group" + Thread.currentThread().getThreadGroup().getName() + ",thread " +Thread.currentThread().getName());
"a".wait();
} catch (InterruptedException e) {
System.out.println("group" + Thread.currentThread().getThreadGroup().getName() + ",thread " +Thread.currentThread().getName() + "terminated!");
e.printStackTrace();
}
}
}
}
}

最终的执行结果是,两个线程先后被激活,在等待了10s过后,两个线程又先后被终止

线程、临界资源、cpu调度 有点像是工人、作业、和工作车间的关系

小结

上面是java线程组的概要介绍,主要是为了方便后续使用快速查阅,如果在查看源码的过程发现新的用法会持续更新