使用:

 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. windows下mingw编译faac

    进入目录先运行 ./bootstrap 接着就可以 ./configure --without-mp4v2 然后 make make install

  2. Android传感器【转】

    本文转载自:http://blog.csdn.net/ffmxnjm/article/details/52101592?locationNum=3&fps=1 传感器的意义 事实上,目前智能手 ...

  3. Oracle.DataAccess.Client.OracleCommand”的类型初始值设定项引发异常

    Oracle.ManagedDataAccess.dll 连接Oracle数据库不需要安装客户端 最开始,连接Oracle 数据是需要安装客户端的,ado.net 后来由于微软未来不再支持 Syste ...

  4. postman通过引入外部文件实现参数化

    postman可通过引入外部文件进行参数化 目录 1.准备好接口信息 2.设置 1.准备好接口信息 这里的usr和psw是要参数化的对象 2.设置 文件准备 添加文件,并设置好循环次数即可

  5. Native SQL的使用

    OPEN SQL也不是万能的,存在一定的局限性.例如后台数据库为Oracle,对数据表中某个字段大小写是不固定的,若以这个字段为查旬条件,一般Oracle处理方法是使用Upper /Lower函数据将 ...

  6. TCP的三次握手过程

    TCP::传输控制协议(Transmission Control Protocol )     是一种面相连接的.可靠的.基于字节流的 传输层通信协议. TCP是一种面相连接的协议.其显著的特点就是在 ...

  7. gts测试流程

    测试目的: 用于检测你做的Android gms包是否满足兼容性要求,通俗点说,gms包,就是Google自己的apk,提供基础服务,例如YouTube.playstore等. 测试前提: 1.发货u ...

  8. Golang中log与fmt区别

    关于使用log与使用fmt的区别 最初的就是直接打印出来,之后一点点升级,比如加上输出的时间,加上goroutine之间的并发操作(打印信息并不能一定按照你规定好的顺序输出来 每次输出的顺序可能会不同 ...

  9. 【Python基础】_2 Python基本语法与常识(迭代优化中...)

    2 Python的基本语法 为了保证Python解释器能顺利编译所编写的代码,也为了程序员对自己和别人所编写的程序易于阅读.维护,对编程语言的语法做一些基本约定是非常必要的. 2.1 编程方式 2.1 ...

  10. python 开启进程两种方法 multiprocessing模块 介绍

    一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu\_count\(\)查看),在python中大部分情况需要使用多进 ...