线程组

数据结构

线程组是⼀个树状的结构,每个线程组下面可以有多个线程或者线程组。线程组可以起到统⼀控制线程的优先级和检查线程的权限的作用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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[]; // 线程组数组
......
}

线程组可以包含线程也可以包含其它线程组

如果在new Thread()时没有显示的指定线程的线程组,那么默认将它的父线程的线程组设置为自己的线程组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ThreadDemo {
public static void main(String[] args) {
new Thread(() -> {
System.out.println("当前线程" + Thread.currentThread().getName() + "的线程组的名字为:"
+ Thread.currentThread().getThreadGroup().getName());
}).start();

System.out.println("main线程的线程组的名字为:"
+ Thread.currentThread().getThreadGroup().getName());
}
}

运行结果:

main线程的线程组的名字为:main
当前线程Thread-0的线程组的名字为:main

Process finished with exit code 0

常用方法

线程组基本的常用方法如下

返回值 方法名
int activeCount() 返回此线程组中活动线程的估计数。
int activeGroupCount() 返回此线程组中活动线程组的估计数。
void checkAccess() 确定当前运行的线程是否有权修改此线程组。
void destroy() 销毁此线程组及其所有子组。
int enumerate(Thread[] list) 把此线程组及其子组中的所有活动线程复制到指定数组中。
int enumerate(Thread[] list, boolean recurse) 把此线程组中的所有活动线程复制到指定数组中。
int enumerate(ThreadGroup[] list) 把对此线程组中的所有活动子组的引用复制到指定数组中。
int enumerate(ThreadGroup[] 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) 设置线程组的最高优先级。
void uncaughtException(Thread t, Throwable e) 当此线程组中的线程因为一个未捕获的异常而停止,并且线程没有设置特定 Thread.uncaughtExceptionHandler时,由 Java Virtual Machine 调用此方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
其中uncaughtExceptionHandler为线程池捕获线程成员的异常接口

public static void testUncatchException() {
ThreadGroup threadGroup1 = new ThreadGroup("group1") {
// 继承ThreadGroup并重新定义以下方法
// 在线程成员抛出unchecked exception
// 会执行此方法
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println(t.getName() + ": " + e.getMessage());
}
};
// 这个线程是threadGroup1的⼀员
Thread thread1 = new Thread(threadGroup1, ()-> {
// 抛出unchecked异常
throw new RuntimeException("测试异常");
});
thread1.start();
}
运行结果:
Thread-0: 测试异常

Process finished with exit code 0

线程优先级

线程中的优先级由低到高指定范围为1~10,默认为5,但是线程执行的本质还有由CPU的调度来决定的,只是通常情况下高优先级的线程更有可能被分配到资源优先执行。

Java提供一个线程调度器来监视和控制处于Runnable状态的线程。其调度方式是抢占式的,在相同优先级的情况下按照”先到先得”的原则进行。

守护线程(Deamon):

守护线程的优先级比较低,某线程是守护线程,如果其它所有的非守护线程结束,这个守护线程也会自动结束。这样的操作可以免去关闭子线程的麻烦。

线程默认是非守护线程,可以通过Thread类中的setDeamon(boolean on)来设置。


线程和线程组都存在优先级,如果属于该线程组的线程的优先级和它的线程组的优先级不一样会发生什么?

1
2
3
4
5
6
7
8
9
10
11
12
public static void diffPriority() {
ThreadGroup threadGroup = new ThreadGroup("t1");
threadGroup.setMaxPriority(6);
Thread thread = new Thread(threadGroup, "thread");
thread.setPriority(9);
System.out.println("我是线程组的优先级" + threadGroup.getMaxPriority());
System.out.println("我是线程的优先级" + thread.getPriority());
}

运行结果:
我是线程组的优先级6
我是线程的优先级6

所以,如果某个线程优先级大于线程所在线程组的最大优先级,那么该线程的优先级将会失效,取而代之的是线程组的最大优先级。

评论