使用:

 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;
}

最新文章

  1. 优化 bulk insert
  2. 分佈式事務故障處理暨ORA-24756: transaction does not exist處理
  3. 【转】jquery两稳定版本比较~~
  4. STC15?MSP430?ARM?DSP?
  5. ng-clip angualr 的copy功能
  6. .xlsx文件总是默认用2007 Microsoft Office component 打开,且无法更改用EXCEL打开的解决方法
  7. OpenStack搭建遇到的问题
  8. Spring的单例模式底层实现
  9. 从输入URL按下回车到页面展现,中间发生了什么?
  10. node.js同步读取与异步读取文件
  11. Ubuntu16 源码方式安装postgresql数据库
  12. jQuery 筛选器 链式编程操作
  13. [转帖][Bash Shell] Shell学习笔记
  14. Nodejs stream模块-翻译
  15. Spring通过ApplicationContext主动获取bean
  16. python daal test
  17. 原生javascript-图片滚动按需加载
  18. PHP代码实现 1
  19. Google Tango SDK下载
  20. angularJs的作用域和依赖注入

热门文章

  1. 转载 用ShadowVolume画模型的影子
  2. Spring的Aop理解
  3. c++11多线程---std::ref和std::cref
  4. windows程序调试
  5. (转)使用NMAP工具扫描端口
  6. JavaScript对象的常用属性及使用
  7. Java使用JDBC连接Hive
  8. Web Service自动化测试知识点导图
  9. 【HANA系列】SAP HANA Studio出现&quot;Fetching Children...&quot;问题
  10. win10安装Tensorflow1.9GPU版本