使用:

 import javax.swing.text.html.HTMLDocument.HTMLReader.IsindexAction;

 public class Test {

     public static void main(String[] args) {

         ThreadGroup tg = new ThreadGroup("threadGroup-001"); 

         Thread t1 = new Thread(tg, new MyThread());
t1.start(); Thread t2 = new Thread(tg, new MyThread());
t2.start(); // 返回线程组中活动线程的估计数
System.out.println("active thread group: " + tg.activeCount());
// 返回此线程组中活动线程组的估计数
System.out.println("activeGroupCount: " + tg.activeGroupCount());
// 检查当前运行的线程是否有权修改此线程组
tg.checkAccess();
// 设置线程组的最高优先级
tg.setMaxPriority(6);
// 返回此线程组的最高优先级
System.out.println("maxPriority: " + tg.getMaxPriority());
// 返回此线程组的名称
System.out.println("thread group name: " + tg.getName());
// 返回此线程组的父线程组
System.out.println(tg.getParent());
// 中断此线程组中的所有线程
tg.interrupt();
// 更改此线程组的后台程序状态
tg.setDaemon(true);
// 测试此线程组是否为一个后台程序线程组
System.out.println("is daemon: " + tg.isDaemon());
// 测试此线程组是否为线程组参数或其祖先线程组之一
System.out.println("is parent: "+ tg.getParent().parentOf(tg));
// 打印线程组信息
tg.list();
// 返回线程组的字符串表示形式
System.out.println(tg.toString());
// 销毁此线程组及其所有子组
tg.destroy();
// 测试此线程组是否已经销毁
System.out.println(tg.isDestroyed());
// System.out.println(tg.);
} private static class MyThread extends Thread {
@Override
public void run() {
System.out.println("thread name: " + Thread.currentThread().getName());
}
} }

一、构造函数

  两种构造函数:

ThreadGroup(String name) 

ThreadGroup(ThreadGroup parent, String name) 

  

// 创建一个线程组必须关联到一个父线程组,默认父线程组是当前线程的线程组Thread.currentThread().getThreadGroup()。
// 并检查父线程组的权限。
public ThreadGroup(String name) {
this(Thread.currentThread().getThreadGroup(), name);
}
 public ThreadGroup(ThreadGroup parent, String name) {
this(checkParentAccess(parent), parent, name);
}
// 初始化此线程组的名称(name)、最高优先级(maxPriority)、daemon、父线程组(parent)
// 并将此线程组添加到父线程组中(parent.add(this))
 private ThreadGroup(Void unused, ThreadGroup parent, String name) {
this.name = name;
this.maxPriority = parent.maxPriority;
this.daemon = parent.daemon;
this.parent = parent;
parent.add(this);
}
// 添加一个线程组到此线程组
 private final void add(ThreadGroup g){
synchronized (this) {
if (destroyed) {
throw new IllegalThreadStateException();
}
// 添加一个线程组到此线程组的groups数组中,groups初始容量为4,每次容量耗尽之后按2倍扩增。
if (groups == null) {
groups = new ThreadGroup[4];
} else if (ngroups == groups.length) {
groups = Arrays.copyOf(groups, ngroups * 2);
}
groups[ngroups] = g; // This is done last so it doesn't matter in case the
// thread is killed
ngroups++;
}
}

二、添加线程到线程组

 ThreadGroup tg = new ThreadGroup("threadGroup-001");
Thread t1 = new Thread(tg, new MyThread());
t1.start();

new Thread(tg, new MyThread()); 调用后,关于线程组相关的操作设置可在 private Thread(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc,boolean inheritThreadLocals)看到:

 private Thread(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
if (name == null) {
throw new NullPointerException("name cannot be null");
} this.name = name; Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
/* Determine if it's an applet or not */ /* If there is a security manager, ask the security manager
what to do. */
if (security != null) {
g = security.getThreadGroup();
} /* If the security manager doesn't have a strong opinion
on the matter, use the parent thread group. */
// 此线程没有明确指定线程组时,为其指定当前线程所在的线程组
if (g == null) {
g = parent.getThreadGroup();
}
} /* checkAccess regardless of whether or not threadgroup is
explicitly passed in. */
g.checkAccess(); /*
* Do we have the required permissions?
*/
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(
SecurityConstants.SUBCLASS_IMPLEMENTATION_PERMISSION);
}
} // 调用类ThreadGroup的addUnstarted函数, 添加一个未启用的线程到线程组
g.addUnstarted(); // 设置当前线程的线程组
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize; /* Set thread ID */
this.tid = nextThreadID();
}

主要操作:设置此线程的线程组,将线程组的未启动线程数加1(addUnstarted() 即nUnstartedThreads++)。

随后启动一个线程(t1.start()):

  public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException(); /* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this); boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}

start()中的先调用 group.add(this)。然后线程启动失败后调用 group.threadStartFailed(this) 。

源码如下:

 void add(Thread t) {
synchronized (this) {
if (destroyed) {
throw new IllegalThreadStateException();
}
// ThreadGroup维护了一个数组,用来存放线程。
if (threads == null) {
threads = new Thread[4];
} else if (nthreads == threads.length) {
threads = Arrays.copyOf(threads, nthreads * 2);
}
// 添加线程到数组中
threads[nthreads] = t; // This is done last so it doesn't matter in case the
// thread is killed
// 线程数组中线程数量增加1
nthreads++; // The thread is now a fully fledged member of the group, even
// though it may, or may not, have been started yet. It will prevent
// the group from being destroyed so the unstarted Threads count is
// decremented.
// 未启动线程数减1
nUnstartedThreads--;
}
}
 void threadStartFailed(Thread t) {
synchronized(this) {
// 线程组中移除线程t
remove(t);
// 未启动线程数增加1
nUnstartedThreads++;
}
}
 private void remove(Thread t) {
synchronized (this) {
if (destroyed) {
return;
}
// 循环遍历查找线程t,并移除
for (int i = 0 ; i < nthreads ; i++) {
if (threads[i] == t) {
System.arraycopy(threads, i + 1, threads, i, --nthreads - i);
// Zap dangling reference to the dead thread so that
// the garbage collector will collect it.
threads[nthreads] = null;
break;
}
}
}
}

由上可见:只有调用start()成功启动的线程才会被它的线程组保存。

三、ThreadGroup的一些函数

1、destory() 销毁此线程组及其所有子组

 // 销毁此线程组及其所有子线程组
public final void destroy() {
int ngroupsSnapshot;
ThreadGroup[] groupsSnapshot;
synchronized (this) {
checkAccess();
if (destroyed || (nthreads > 0)) {
throw new IllegalThreadStateException();
}
// 子线程组数量
ngroupsSnapshot = ngroups;
// 子线程组数组
if (groups != null) {
groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
// 置空子线程数量、子线程组、子线程组数量、子线程组数组
if (parent != null) {
destroyed = true;
ngroups = 0;
groups = null;
nthreads = 0;
threads = null;
}
}
// 递归子线程组
for (int i = 0 ; i < ngroupsSnapshot ; i += 1) {
groupsSnapshot[i].destroy();
}
// 从父线程组中移除此线程组
if (parent != null) {
parent.remove(this);
}
}

2、interrupt() 中断此线程组中的所有线程(包括子线程组中的线程)

  // 中断此线程组中的所有线程(包括子线程组中的线程)
public final void interrupt() {
int ngroupsSnapshot;
ThreadGroup[] groupsSnapshot;
synchronized (this) {
checkAccess();
// 循环遍历线程组中的子线程,中断线程
for (int i = 0 ; i < nthreads ; i++) {
threads[i].interrupt();
}
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
}
// 递归去子线程组执行interrupt()
for (int i = 0 ; i < ngroupsSnapshot ; i++) {
groupsSnapshot[i].interrupt();
}
}

3、setMaxPriority 设置线程组(包括子线程组)的最高优先级

  // 设置线程组(包括子线程组)的最高优先级
public final void setMaxPriority(int pri) {
int ngroupsSnapshot;
ThreadGroup[] groupsSnapshot;
synchronized (this) {
checkAccess();
// 检验优先级大小是否合规
if (pri < Thread.MIN_PRIORITY || pri > Thread.MAX_PRIORITY) {
return;
}
// 最高优先级不能大于父线程组
maxPriority = (parent != null) ? Math.min(pri, parent.maxPriority) : pri;
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
}
// 递归设置子线程组的最高优先级
for (int i = 0 ; i < ngroupsSnapshot ; i++) {
groupsSnapshot[i].setMaxPriority(pri);
}
}

4、parentOf 判断是否为当前线程组的祖先线程组(或是否是当前线程组)

 // 判断g是否为当前线程组的祖先线程组(或是否是当前线程组)
public final boolean parentOf(ThreadGroup g) {
// 向上查找父线程组,直到父线程组为空,判断g是否为当前线程组的祖先线程组(或是否是当前线程组)
for (; g != null ; g = g.parent) {
if (g == this) {
return true;
}
}
return false;
}

5、activeCount 返回线程组中活动线程的估计数

 // 返回线程组中活动线程的估计数
public int activeCount() {
int result;
// Snapshot sub-group data so we don't hold this lock
// while our children are computing.
int ngroupsSnapshot;
ThreadGroup[] groupsSnapshot;
synchronized (this) {
if (destroyed) {
return 0;
}
// 线程组中的线程数
result = nthreads;
// 子线程组
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
}
// 递归子孙线程组
for (int i = 0 ; i < ngroupsSnapshot ; i++) {
result += groupsSnapshot[i].activeCount();
}
return result;
}

6、activeGroupCount 返回此线程组中活动线程组的估计数

 public int activeGroupCount() {
int ngroupsSnapshot;
ThreadGroup[] groupsSnapshot;
synchronized (this) {
if (destroyed) {
return 0;
}
// 子线程组数量
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
}
int n = ngroupsSnapshot;
// 递归子孙线程组
for (int i = 0 ; i < ngroupsSnapshot ; i++) {
n += groupsSnapshot[i].activeGroupCount();
}
return n;
}

7、enumerate 所有活动线程复制到指定数组中

 // rescurse 否还包括作为此线程组的子组的线程组中的线程。
// n 是list中已经存在的元素(线程)数量
private int enumerate(Thread list[], int n, boolean recurse) {
int ngroupsSnapshot = 0;
ThreadGroup[] groupsSnapshot = null;
synchronized (this) {
if (destroyed) {
return 0;
}
// 线程组中的线程
int nt = nthreads;
// nt不能大于list的可用长度(递归遍历子孙线程组的时候,会带上n,所以此处要减去n)
if (nt > list.length - n) {
nt = list.length - n;
}
for (int i = 0; i < nt; i++) {
if (threads[i].isAlive()) {
list[n++] = threads[i];
}
}
// 子孙线程组
if (recurse) {
ngroupsSnapshot = ngroups;
if (groups != null) {
groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
} else {
groupsSnapshot = null;
}
}
}
// 递归子孙线程组
if (recurse) {
for (int i = 0 ; i < ngroupsSnapshot ; i++) {
n = groupsSnapshot[i].enumerate(list, n, true);
}
}
// 返回已添加到list的线程数量
return n;
}

java ThreadGroup源码分析的更多相关文章

  1. Java Reference 源码分析

    @(Java)[Reference] Java Reference 源码分析 Reference对象封装了其它对象的引用,可以和普通的对象一样操作,在一定的限制条件下,支持和垃圾收集器的交互.即可以使 ...

  2. Java 集合源码分析(一)HashMap

    目录 Java 集合源码分析(一)HashMap 1. 概要 2. JDK 7 的 HashMap 3. JDK 1.8 的 HashMap 4. Hashtable 5. JDK 1.7 的 Con ...

  3. java集合源码分析(三):ArrayList

    概述 在前文:java集合源码分析(二):List与AbstractList 和 java集合源码分析(一):Collection 与 AbstractCollection 中,我们大致了解了从 Co ...

  4. java集合源码分析(六):HashMap

    概述 HashMap 是 Map 接口下一个线程不安全的,基于哈希表的实现类.由于他解决哈希冲突的方式是分离链表法,也就是拉链法,因此他的数据结构是数组+链表,在 JDK8 以后,当哈希冲突严重时,H ...

  5. Java集合源码分析(六)TreeSet<E>

    TreeSet简介 TreeSet 是一个有序的集合,它的作用是提供有序的Set集合.它继承于AbstractSet抽象类,实现了NavigableSet<E>, Cloneable, j ...

  6. Java集合源码分析(五)HashSet<E>

    HashSet简介 HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持.它不保证set 的迭代顺序:特别是它不保证该顺序恒久不变.此类允许使用null元素. HashSet源 ...

  7. Java集合源码分析(四)Vector<E>

    Vector<E>简介 Vector也是基于数组实现的,是一个动态数组,其容量能自动增长. Vector是JDK1.0引入了,它的很多实现方法都加入了同步语句,因此是线程安全的(其实也只是 ...

  8. Java集合源码分析(三)LinkedList

    LinkedList简介 LinkedList是基于双向循环链表(从源码中可以很容易看出)实现的,除了可以当做链表来操作外,它还可以当做栈.队列和双端队列来使用. LinkedList同样是非线程安全 ...

  9. Java集合源码分析(二)ArrayList

    ArrayList简介 ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单线程环境下,多线 ...

随机推荐

  1. SOUI3.0仿Android插值动画使用方法

    在Android系统中,有插值动画,数值动画,属性动画,帧动画. 帧动画,在SOUI里可以通过AnimateImg这个控件来实现,其它几种动画3.0之前不支持,需要类似动画效果,只能自己通过定时器去实 ...

  2. ubuntu的无线网无法连上

    自己的笔记本可以连上wireless,但是实验室的台式机无法连上. 有无线显示,就是无法连上. 后来把连在机箱上的网线拔了以后可以连无线了.如果有网线连接,系统优先会选择有线的上网.

  3. 2018-5 - 热经 - 北京中地时空数码科技有限公司 - 研发工程师(WEBGIS 方向)

    一面: 登记,填写个人信息 笔试 选择题: HTML,CSS,JS 的选择题,都是基础题.其中有一道问哪个不是 document 的属性或方法,我在 bgColor 和 focus() 上面纠结了一下 ...

  4. Python基本语法_基本数据类型_数值型详解

    目录 目录 软件环境 Python变量调用的过程 数值型 删除一个数值类型对象 布尔型 Bool 标准整型 Int 长整型 双精度浮点型 Float 复数 数值类型对象的内建功能函数 absNumbe ...

  5. Python学习之==>模块结构调整

    一.为什么要进行模块结构调整 当一个脚本中有大量的配置.方法及接口时,脚本显得十分臃肿,可读性很差.为了提高代码的易读性,可以将一个繁杂的脚本根据不同的功能放在不同的目录下分类管理,这整个过程叫做模块 ...

  6. 练习1:python设计停车入库出库系统

    前言: 最近在某个测试群看到有人抛出了一个面试题.为了提升自己的编程能力,我也尝试的用python去写了一下. 语言:python,数据库:sqlite  .菜鸟来袭,只是基本实现功能,可能没有考虑太 ...

  7. 求一个集合S中m个元素的所有排列以及一个数组A的全排列—递归实现版完整代码

    说明,本文全文代码均用dart语言实现. 求一个集合S中m个元素的所有排列情况,并打印,非常适合用递归的思路实现.本文给出了两种实现方法,一种是给定的填充排列数组长度是固定的,一种是可变长度的.两种方 ...

  8. face-api.js 前端人脸识别,人脸检测,登录认证

    1.参考face-api.js https://github.com/justadudewhohacks/face-api.js#face-api.js-for-the-browser

  9. zabbix_server.conf

    ListenPort=10051 LogFile=/var/log/zabbix/zabbix_server.log LogFileSize=0 PidFile=/var/run/zabbix/zab ...

  10. vue-devtools安装以后,勾选了“允许访问文件网址”之后还是无法使用

    勾选了“允许访问文件网址”,还是无法使用: Vue.js is detected on this page. Devtools inspection is not available because ...