使用:

 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. List of Mozilla-Based Applications

    List of Mozilla-Based Applications The following is a list of all known active applications that are ...

  2. Sqlserver 创建账号

    下面是通过脚本创建账号,创建一个appuser 的账号,密码:123456,可操作的DB:TEST 赋予权限,增删改查,操作视图,存储过程.当然当前的账号要有足够的权限. create login a ...

  3. HTM基础之HTML标签

    HTML(超文本标记语言) html代码实际上就是一套能够被浏览器所识别的规则代码,由一个个标签组成.html代码就是一大长串字符串,而这种字符串的格式正好能够被浏览器所识别,也就有了我们的WEB页面 ...

  4. apue 在 mac 环境编译错误

    参考资料:https://unix.stackexchange.com/questions/105483/compiling-code-from-apue 笔者使用 mac 学习 apue, 在编译的 ...

  5. 那些堪称神器的 Chrome 插件

    Chrome 的简洁快速以及丰富的插件种类使得它在国内日益盛行,帮助了我们很多 Chrome 用户提升了工作效率,而今天要给大家推荐8款实用甚至堪称神器的 Chrome 插件,希望对提升大家的工作效率 ...

  6. ubuntu 安装企业级容器 docker harbor

    安装docker harbor 企业级容器   环境说明: 操作系统: ubuntu16.04.5 LTS IP地址:  192.168.31.129   https://github.com/goh ...

  7. Vue 2.0 入门系列(15)学习 Vue.js 需要掌握的 es6 (2)

    类与模块 类 es6 之前,通常使用构造函数来创建对象 // 构造函数 User function User(username, email) { this.username = username; ...

  8. JavaScript ES6 class指南

    前言 EcmaScript 2015 (又称ES6)通过一些新的关键字,使类成为了JS中一个新的一等公民.但是目前为止,这些关于类的新关键字仅仅是建立在旧的原型系统上的语法糖,所以它们并没有带来任何的 ...

  9. vue组件化编程应用

    写几个小案例来理解vue的组件化编程思想,下面是一个demo. 效果图示: 功能: Add组件用于添加用户评论,提交后右边评论回复会立马显示数据.Item组件点击删除可以删除当前用户评论.当List组 ...

  10. 图论 test solution

    图论 test solution T1:潜伏 题目背景 小悠回家之后,跟着母亲看了很多抗日神剧,其中不乏一些谍战片. 题目描述 解放前夕,北平城内潜伏着若干名地下党员,他们居住在城市的不同位置.现在身 ...