线程组
一个线程组代表一组线程。此外,一个线程组还可以包括其他线程组。线程组形成一棵树,其中除了初始线程组之外的每个线程组都有一个父级。
允许线程访问有关其自己的线程组的信息,但不能访问有关其线程组的父线程组或任何其他线程组的信息。可以使用线程组对线程进行批量控制。
代码示例
public static void main(String[] args) {
Thread testThread = new Thread(() -> {
System.out.println("testThread当前线程组名字:" +
Thread.currentThread().getThreadGroup().getName());
System.out.println("testThread线程名字:" +
Thread.currentThread().getName());
});
testThread.start();
System.out.println("执行main所在线程的线程组名字: " + Thread.currentThread().getThreadGroup().getName());
System.out.println("执行main方法线程名字:" + Thread.currentThread().getName());
}
执行结果:
ThreadGroup管理着它下面的Thread,ThreadGroup是一个标准的向下引用的树状结构,这样设计的原因是防止"上级"线程被"下级"线程引用而无法有效地被GC回收。
线程的优先级
// 最小优先级
public static final int MIN_PRIORITY = 1;
// 默认优先级
public static final int NORM_PRIORITY = 5;
// 最大优先级
public static final int MAX_PRIORITY = 10;
高优先级的线程比低优先级的线程有更高的几率得到执行,不是线程优先级高就一定先执行,操作系统接收到java程序的优先级设置并不一定会采纳,最终的调用顺序由操作系统的线程调度算法决定,我们可以通过setPriority(int newPriority)设置线程的优先级。
代码示例
public static void main(String[] args) {
Thread thread1 = new Thread();
System.out.println("默认线程优先级:"+thread1.getPriority());
Thread thread2 = new Thread();
thread2.setPriority(10);
System.out.println("设置线程为最大优先级优先级:"+thread2.getPriority());
Thread thread3 = new Thread();
// java.lang.IllegalArgumentException
thread3.setPriority(11);
System.out.println("非法参数:"+thread3.getPriority());
}
执行结果为:
设置优先级源码:
public final void setPriority(int newPriority) {
this.checkAccess();
if (newPriority <= 10 && newPriority >= 1) {
ThreadGroup g;
if ((g = this.getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
this.setPriority0(this.priority = newPriority);
}
} else {
throw new IllegalArgumentException();
}
}
从上面的设置优先级的源码中我们可以看到,当我们设置的线程的优先级大于线程所在线程组最大的优先级的时候,线程的优先级会被覆盖。
线程组构造器与常用方法
构造器
// public ThreadGroup(String name)
构造一个新的线程组。这个新组的父组是当前运行线程的线程组。
调用父线程组的checkAccess方法,不带参数;这可能会导致安全异常。
参数:
name - 新线程组的名称。
抛出:
SecurityException - 如果当前线程无法在指定线程组中创建线程
public ThreadGroup(String name) {
this(Thread.currentThread().getThreadGroup(), name);
}
//public ThreadGroup(ThreadGroup parent, String name)
创建一个新的线程组。这个新组的父级是指定的线程组。
调用父线程组的checkAccess方法,不带参数;这可能会导致安全异常。
参数:
parent - 父线程组。
name - 新线程组的名称。
抛出:
NullPointerException - 如果线程组参数为null 。
SecurityException - 如果当前线程无法在指定线程组中创建线程。
public ThreadGroup(ThreadGroup parent, String name) {
this(checkParentAccess(parent), parent, name);
}
常用方法
// 两种方式->获取当前线程所在线程组的活动线程总数(估计)。
// 方式一
threadGroup.activeCount()
// 方式二
Thread.activeCount()
// 获取当前线程组的父线程组
threadGroup.getParent()
// 返回该线程所属的线程组。如果此线程已终止(已停止),则此方法返回 null
Thread.currentThread().getThreadGroup()
// 复制一个线程组到一个线程数组(获取Thread信息)
Thread[] threads = new Thread[threadGroup.activeCount()];
threadGroup.enumerate(threads);
总结
线程组是一个树状的结构,每个线程组下面可以有多个线程或者线程组。线程组可以起到统一控制线程的优先级和检查线程的权限的作用,但是由于线程调度是抢占式,并不是优先级高的就一定先执行。