暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

ThreadGroup详解(下)

Alleria Windrunner 2020-05-06
187

ThreadGroup操作

ThreadGroup 并不能提供对线程的管理,ThreadGroup 的主要功能是对线程进行组织,在本篇中,将详细介绍 ThreadGroup 的主要方法。
ThreadGroup的基本操作
  • activeCount()用于获取 group 中活跃的线程,这只是个估计值,并不能百分之百地保证数字一定正确,原因前面已经分析过,该方法会递归获取其他子 group 中的活跃线程。

  • activeGroupCount()用于获取 group 中活跃的子 group,这也是一个近似估值,该方法也会递归获取所有的子 group。

  • getMaxPriority()用于获取 group 的优先级,默认情况下,Group 的优先级为10,在该 group 中,所有线程的优先级都不能大于 group 的优先级。

  • getName()用于获取 group 的名字。

  • getParent()用于获取 group 的父 group,如果父 group 不存在,则会返回 null,比如 system group 的父 group 就为 null。

  • list()该方法没有返回值,执行该方法会将 group 中所有的活跃线程信息全部输出到控制台,也就是 System.out。

  • parentOf(ThreadGroup g)会判断当前 group 是不是给定 group 的父 group,另外如果给定的 group 就是自己本身,那么该方法也会返回 true。

  • setMaxPriority(int pri)会指定 group 的最大优先级,最大优先级不能超过父 group 的最大优先级,执行该方法不仅会改变当前 group 的最大优先级,还会改变所有子 group 的最大优先级。


下面我们给出一个简单的例子来测试一下上面的几个方法。
    public class ThreadGroupBasic
    {
    public static void main(String[] args) throws InterruptedException
    {


    /*
    * Create a thread group and thread.
    */
    ThreadGroup group = new ThreadGroup("group1");
    Thread thread = new Thread(group, () ->
    {
    while (true)
    {
    try
    {
    TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e)
    {
    e.printStackTrace();
    }
    }
    }, "thread");
    thread.setDaemon(true);
    thread.start();


    //make sure the thread is started
    TimeUnit.MILLISECONDS.sleep(1);


    ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();


    System.out.println("activeCount=" + mainGroup.activeCount());
    System.out.println("activeGroupCount=" + mainGroup.activeGroupCount());
    System.out.println("getMaxPriority=" + mainGroup.getMaxPriority());
    System.out.println("getName=" + mainGroup.getName());
    System.out.println("getParent=" + mainGroup.getParent());
    mainGroup.list();
    System.out.println("--------------------------");
    System.out.println("parentOf="+mainGroup.parentOf(group));
    System.out.println("parentOf="+mainGroup.parentOf(mainGroup));
    }
    }
    这里需要特别说明的是 setMaxPriority,在深入理解Thread构造函数篇中,我们通过分析源码得出结论,线程的最大优先级,不能高于所在线程组的最大优先级,但是如果我们把代码写成下面这样会怎么样呢?
    运行上面的程序,会出现 thread 的优先级大于所在 group 最大优先级的情况,如下所示:
      group.getMaxPriority()=10
      thread.getPriority()=5
      group.getMaxPriority()=3
      thread.getPriority()=5
      虽然出现了已经加入该 group 的线程的优先级大于 group 最大优先级的情况,但是后面加入该 group 的线程再不会大于新设置的值:3,这一点需要大家注意。

      ThreadGroup的interrupt
      interrupt 一个 thread group 会导致该 group 中所有的 active 线程都被 interrupt,也就是说该 group 中每一个线程的 interrupt 标识都被设置了,下面是 ThreadGroup 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;
        }
        }
        for (int i = 0 ; i < ngroupsSnapshot ; i++) {
        groupsSnapshot[i].interrupt();
        }
        }
        分析上述源码,我们可以看出在 interrupt 内部会执行所有 thread 的 interrupt 方法,并且会递归获取子 group,然后执行它们各自的 interrupt 方法,下面我们写个简单的程序测试一下:
          public class ThreadGroupInterrupt
          {
          public static void main(String[] args) throws InterruptedException
          {


          ThreadGroup group = new ThreadGroup("TestGroup");


          new Thread(group, () ->
          {
          while (true)
          {
          try
          {
          TimeUnit.MILLISECONDS.sleep(2);
          } catch (InterruptedException e)
          {
          //received interrupt SIGNAL and clear quickly
          break;
          }
          }
          System.out.println("t1 will exit.");
          }, "t1").start();


          new Thread(group, () ->
          {
          while (true)
          {
          try
          {
          TimeUnit.MILLISECONDS.sleep(1);
          } catch (InterruptedException e)
          {
          //received interrupt SIGNAL and clear quickly
          break;
          }
          }
          System.out.println("t2 will exit.");
          }, "t2").start();


          //make sure all of above threads started.
          TimeUnit.MILLISECONDS.sleep(2);


          group.interrupt();
          }
          }
          上面的代码足够简单,不必多做解释,从运行结果中可以看出,group 中的 active thread 都将被 interrupt。

          ThreadGroup的destroy

          destroy 用于销毁 ThreadGroup,该方法只是针对一个没有任何 active 线程的 group 进行一次 destroy 标记,调用该方法的直接结果是在父 group 中将自己移除:

            Destroys this thread group and all of its subgroups. This thread  group must be empty, indicating that all threads that had been in this thread group have since stopped.(销毁 ThreadGroup 及其子 ThreadGroup,在该 ThreadGroup 中所有的线程必须是空的,也就是说 ThreadGroup 或者子 ThreadGroup 所有的线程都已经停止运行,如果有 Active 线程存在,调用 destroy 方法则会抛出异常。)

            下面我们写一个简单的代码对其进行测试:

              public class ThreadGroupDestroy
              {


              public static void main(String[] args)
              {
              ThreadGroup group = new ThreadGroup("TestGroup");


              ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
              System.out.println("group.isDestroyed=" + group.isDestroyed());
              mainGroup.list();


              group.destroy();


              System.out.println("group.isDestroyed=" + group.isDestroyed());
              mainGroup.list();
              }
              }

              程序的运行结果如下所示,其中 isDestroyed 方法是判断 ThreadGroup 是否被 destroy 了:

                ggroup.isDestroyed=false
                java.lang.ThreadGroup[name=main,maxpri=10]
                Thread[main,5,main]
                Thread[Monitor Ctrl-Break,5,main]
                java.lang.ThreadGroup[name=TestGroup,maxpri=10]
                group.isDestroyed=true
                java.lang.ThreadGroup[name=main,maxpri=10]
                Thread[main,5,main]
                Thread[Monitor Ctrl-Break,5,main]

                守护ThreadGroup

                线程可以设置为守护线程,ThreadGroup 也可以设置为守护 ThreadGroup,但是若将一个 ThreadGroup 设置为 daemon,也并不会影响线程的 daemon 属性,如果一个 ThreadGroup 的 daemon 被设置为 true,那么在 group 中没有任何 active 线程的时候该 group 将自动 destroy,下面我们给出一个简单的例子来对其进行说明:

                  public class ThreadGroupDaemon
                  {
                  public static void main(String[] args)
                  throws InterruptedException
                  {


                  ThreadGroup group1 = new ThreadGroup("Group1");
                  new Thread(group1, () ->
                  {
                  try
                  {
                  TimeUnit.SECONDS.sleep(1);
                  } catch (InterruptedException e)
                  {
                  e.printStackTrace();
                  }
                  }, "group1-thread1").start();


                  ThreadGroup group2 = new ThreadGroup("Group2");
                  new Thread(group2, () ->
                  {
                  try
                  {
                  TimeUnit.SECONDS.sleep(1);
                  } catch (InterruptedException e)
                  {
                  e.printStackTrace();
                  }
                  }, "group2-thread1").start();


                  //设置 daemon 为 true
                  group2.setDaemon(true);


                  TimeUnit.SECONDS.sleep(3);
                  System.out.println(group1.isDestroyed());
                  System.out.println(group2.isDestroyed());
                  }
                  }

                  在上面的代码中,第二个 group 的 daemon 被设置为 true,当其中没有 active 线程的时候,该 group 将会自动被 destroy,而第一个 group 则相反。

                  文章转载自Alleria Windrunner,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                  评论