JDK8中ThreadGroup源码解析

来源:互联网 发布:windows所有系统 编辑:程序博客网 时间:2024/05/21 21:50

  

  许多线程聚集成组即线程组,线程组可以包括其他线程组,线程组随着层级的增加可形成树,其中的每个线程组除了初始化线程组外都存在着父线程组。线程允许访问关于它自己的线程组的信息,但不允许访问其线程组的父线程组或任何其他线程组的信息。当需要锁定策略的时候,线程组成子线程组到父线程组是尽可能地锁定一个级别的树,但是不锁住树的底部。这样可以限制需要持有的锁的数量,特别是避免为根线程组(或全局锁)获取锁,这锁将是多处理器系统中许多线程组争用的资源。这样的锁定策略通常会导致获取一个线程组状态的快照,并在该快照中工作,而不是在执行的时候将线程组锁住。

  1.ThreadGroup初始化

  ThreadGroup有提供构造方法,可以自行进行初始化设置或者自行交给Thread处理,因为在new Thread()时会默认初始化线程组ThreadGroup。关于ThreadGroup的初始化可以参考Thread的源码解析:http://ericchunli.iteye.com/blog/2394118。

  2.ThreadGroup源码解析

  public class ThreadGroup implements Thread.UncaughtExceptionHandler {

  private final ThreadGroup parent; // 父线程组

  String name; // 线程组名称

  int maxPriority; // 线程组优先级

  boolean destroyed; // 是否已经被销毁

  boolean daemon; // 守护线程

  boolean vmAllowSuspension; // 供VM使用

  int nUnstartedThreads = 0; // 线程组中未启动的线程

  int nthreads; // 线程数量

  Thread threads[]; // 线程

  int ngroups; // 线程组数量

  ThreadGroup groups[]; // 线程组

  // 创建系统线程组,不在任何线程组中的空线程组

  private ThreadGroup() { // called from C code

  this.name = "system";

  this.maxPriority = Thread.MAX_PRIORITY;

  this.parent = null;

  }

  public ThreadGroup(String name) {

  this(Thread.currentThread().getThreadGroup(), name);

  }

  public ThreadGroup(ThreadGroup parent, String name) {

  this(checkParentAccess(parent), parent, name);

  }

  // 线程组对外提供了两个构造函数来进行初始化参数设置

  private ThreadGroup(Void unused, ThreadGroup parent, String name) {

  this.name = name;

  this.maxPriority = parent.maxPriority;

  this.daemon = parent.daemon;

  this.vmAllowSuspension = parent.vmAllowSuspension;

  this.parent = parent;

  parent.add(this); // 把当前线程组添加到父线程组

  // 由以上构造函数可得出几乎每个线程组都存在着父线程组

  }

  // 给线程组设置优先级即:给线程组当中的每个线程设置优先级

  public final void setMaxPriority(int pri) {

  int ngroupsSnapshot;

  ThreadGroup[] groupsSnapshot; // 线程组状态的快照

  synchronized (this) {

  // object的对象锁,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞,不影响非同步方法的访问

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

  }

  // 这里采用递归调用设置线程组中每个线程的优先级

  }

  public final void checkAccess() {

  SecurityManager security = System.getSecurityManager();

  if (security != null) {

  security.checkAccess(this);

  }

  }

  // 返回线程组及其子线程组中活动线程数,返回的只是估计值,因为在这个方法遍历内部数据结构时,线程的数量可能会动态变化,并且可能会受到某些系统线程的影响。此方法主要用于调试和监视目的。

  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;

  }

  // 用来中断线程组中的所有线程,类似setMaxPriority的实现

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

  // Arrays.copyOf可看下它的底层实现,很有用且到处用到

  } else {

  groupsSnapshot = null;

  }

  }

  for (int i = 0 ; i < ngroupsSnapshot ; i++) {

  groupsSnapshot[i].interrupt();

  }

  }

  // 除了当前线程,剩下的全部干掉,只存在当前线程在线程组则直接返回true

  @SuppressWarnings("deprecation")

  private boolean stopOrSuspend(boolean suspend) {

  boolean suicide = false;

  Thread us = Thread.currentThread();

  int ngroupsSnapshot;

  ThreadGroup[] groupsSnapshot = null;

  synchronized (this) {

  checkAccess();

  for (int i = 0 ; i < nthreads ; i++) {

  if (threads[i]==us)

  suicide = true;

  else if (suspend)

  threads[i].suspend();

  else

  threads[i].stop();

  }

  ngroupsSnapshot = ngroups;

  if (groups != null) {

  groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);

  }

  }

  for (int i = 0 ; i < ngroupsSnapshot ; i++)

  suicide = groupsSnapshot[i].stopOrSuspend(suspend) || suicide;

  return suicide;

  }

  // 在Thread销毁的时候会销毁所属线程组信息,即调用Thread的exit()方法时会调用线程组的threadTerminated()方法,threadTerminated会调用当前方法

  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); // 从父线程组中移除当前线程组

  }

  }

  // 仅供构造函数使用,注意默认的构造线程组是:4

  private final void add(ThreadGroup g){

  synchronized (this) {

  if (destroyed) {

  throw new IllegalThreadStateException();

  }

  if (groups == null) {

  groups = new ThreadGroup[4];

  } else if (ngroups == groups.length) {

  // 不相等的情形,remove()执行完毕但是groups[ngroups]=null,GC未执行?

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

  }

  }

  // 从线程组中删除指定的线程组

  private void remove(ThreadGroup g) {

  synchronized (this) {

  if (destroyed) {

  return;

  }

  // 循环遍历,存在再进行处理

  for (int i = 0 ; i < ngroups ; i++) {

  if (groups[i] == g) {

  ngroups -= 1;

  System.arraycopy(groups, i + 1, groups, i, ngroups - i);

  // Zap dangling reference to the dead group so that the GC will collect it.

  groups[ngroups] = null;

  break;

  }

  }

  if (nthreads == 0) {

  notifyAll(); 唤醒synchronized (this)?

  }

  if (daemon && (nthreads == 0) &&

  (nUnstartedThreads == 0) && (ngroups == 0))

  {

  destroy(); // 不理解为什么得是daemon?

  }

  }

  }

  // 在new Thread()时会被调动,增加未启动线程的数量

  void addUnstarted() {

  synchronized(this) {

  if (destroyed) {

  throw new IllegalThreadStateException();

  }

  nUnstartedThreads++;

  }

  }

  // new Thread().start()时会调用此方法,类似add(ThreadGroup g)的实现

  void add(Thread t) {

  synchronized (this) {

  if (destroyed) {

  throw new IllegalThreadStateException();

  }

  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

  nthreads++;

  // 此时就算CPU没有执行,也会被阻止被销毁,未启动数量减1

  nUnstartedThreads--;

  }

  }

  // start失败的原因,重复调用start()方法?

  void threadStartFailed(Thread t) {

  synchronized(this) {

  remove(t);

  nUnstartedThreads++;

  }

  }

  // 在Thread的exit()方法中被调用

  void threadTerminated(Thread t) {

  synchronized (this) {

  remove(t);

  if (nthreads == 0) {

  notifyAll();

  }

  if (daemon && (nthreads == 0) &&

  (nUnstartedThreads == 0) && (ngroups == 0))

  {

  destroy();

  }

  }

  }

  // 此处类似remove(ThreadGroup g)的实现

  private void remove(Thread t) {

  synchronized (this) {

  if (destroyed) {

  return;

  }

  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 GC will collect it.

  threads[nthreads] = null;

  break;

  }

  }

  }

  }

  // 未指定Thread.UncaughtExceptionHandler且线程在线程组中被stop时会被JVM调用

  * 遵循以下规则:小腹左侧痛是怎么回事呢?

  *

  If this thread group has a parent thread group, the

  * uncaughtException method of that parent is called

  * with the same two arguments.

  *

  Otherwise, this method checks to see if there is a

  * {@linkplain Thread#getDefaultUncaughtExceptionHandler default

  * uncaught exception handler} installed, and if so, its

  * uncaughtException method is called with the same

  * two arguments.成都做阴茎延长术哪好

  *

  Otherwise, this method determines if the Throwable

  * argument is an instance of {@link ThreadDeath}. If so, nothing

  * special is done. Otherwise, a message containing the

  * thread's name, as returned from the thread's {@link

  * Thread#getName getName} method, and a stack backtrace,

  * using the Throwable's {@link

  * Throwable#printStackTrace printStackTrace} method, is

  * printed to the {@linkplain System#err standard error stream}.

  * 此方法可以被线程组的子类重写以提供不同的实现 //

  public void uncaughtException(Thread t, Throwable e) {

  if (parent != null) {

  parent.uncaughtException(t, e);

  } else {

  Thread.UncaughtExceptionHandler ueh =

  Thread.getDefaultUncaughtExceptionHandler();

  if (ueh != null) {

  ueh.uncaughtException(t, e);

  } else if (!(e instanceof ThreadDeath)) {

  System.err.print("Exception in thread \""

  + t.getName() + "\" ");

  e.printStackTrace(System.err);

  }

  }

  }

  // Used by VM to control lowmem implicit suspension.

  @Deprecated成都治疗阳痿的费用高不?

  public boolean allowThreadSuspension(boolean b) {

  this.vmAllowSuspension = b;

  if (!b) {

  VM.unsuspendSomeThreads();

  }

  return true;

  }

  public String toString() {

  return getClass().getName()+"[name="+getName()+",maxpri="+maxPriority+"]";

  }

  }

  Note:此处只简单介绍常见的方法实现,因为ThreadGroup的源码还算简单且实际运用中也很少被提及。如果要更好的了解ThreadGroup,需要结合Thread和ThreadDeath源码共同理解。

原创粉丝点击