• Java多线程编程(7)--线程组与线程工厂


    一.线程组

      实际上,线程组是一个设计失败的概念。它最初是出于安全的考虑被设计用来隔离不同的applet(已过时)的。然而,ThreadGroup并未实现这一预期目标,并且它所实现的许多方法是有缺陷的。但是ThreadGroup仍然遗留在其他和线程有关的类中,因此这里只是对它进行一个简单的介绍。在大多数情况下,我们完全可以忽略线程组这一概念以及它的存在。
      一个线程组代表了一组线程。此外,一个线程组也能包含其他的线程组。线程与线程组的关系类似于文件和文件夹的关系,即一个文件总是位于特定的文件夹中,而一个文件夹可以包含多个文件和文件夹。通过线程组可以很方便的对多个线程进行管理。下图展示了线程组与线程及其他线程组的关系:

      上面的线程和线程组组成了一棵树,除了根线程组外,其他每个线程组都有一个父线程组。
      Thread类有几个构造器允许我们在创建线程的时候指定其所属的线程组。如果在创建线程的时候没有指定线程组,那么这个线程就属于其父线程所属的线程组。因此,每一个线程都一个线程组与之关联。

    1.成员变量

      Java中使用ThreadGroup类来表示线程组。先来看这个类有哪些成员变量:

    • parent:父线程组;
    • name:线程组名称;
    • maxPriority:最大优先级。该线程组中的每个线程的优先级都不能超过这个值。
    • destroyed:该线程组是否已经被销毁。
    • daemon:是否为守护线程组。线程组是否为守护线程组与其管理的线程是否为守护线程没有关系,但概念类似。即若某线程组为守护线程组,则当该线程组的最后一个线程被停止或最后一个线程组被销毁后,该线程组将会自动销毁。
    • nUnstartedThreads:线程组中未启动的线程个数。
    • nthreads:线程组中已启动的线程个数,不包含子线程组中的线程;
    • threads:用来存储线程组中线程的数组,不包含未启动的线程;
    • ngroups:线程组中子线程组的个数,不包含子线程组中的线程组;
    • groups:用来存储线程组中子线程组的数组。

    2.构造方法

      接着继续来看ThreadGroup的构造方法:

    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.parent = parent;
        parent.add(this);
    }
    

      ThreadGroup有两个public的构造方法可以供我们使用,其中ThreadGroup(ThreadGroup parent, String name)可以指定父线程组,而ThreadGroup(String name)则默认以当前线程所在的线程组作为父线程组。
      实际上,ThreadGroup还有一个无参的构造方法:

    /**
     * Creates an empty Thread group that is not in any Thread group.
     * This method is used to create the system Thread group.
     */
    private ThreadGroup() {     // called from C code
        this.name = "system";
        this.maxPriority = Thread.MAX_PRIORITY;
        this.parent = null;
    }
    

      这个构造方法用于创建系统线程组,它会在JVM启动的时候被底层C语言代码来调用。系统线程组是所有线程组的祖先,它没有父线程组。

    3.成员方法

      下面介绍ThreadGroup的几个成员方法:

    • int activeCount()

      返回线程组和子线程组中活跃的线程数。这是一个估值,因为在遍历线程的过程中,有些线程可能已经停止。

    • int activeGroupCount()

      返回线程组和子线程组中活跃的线程组数。线程组只有两种状态,active和destroyed,因此未被销毁的线程组都是活跃的线程组。这也是一个估值,因为在遍历线程组的过程中,有些线程组可能已经被销毁。

    • void destroy()

      销毁当前线程组。若线程组已被销毁或包含活跃的线程时该方法将会抛出异常。

    • int enumerate​(Thread[] list)

      将该线程组及子线程组中活跃的线程拷贝至指定的数组。

    • int enumerate​(Thread[] list, boolean recurse)

      将该线程组及子线程组(可选,recurse为false时只拷贝该线程组中活跃的线程)中活跃的线程拷贝至指定的数组。

    • int enumerate​(ThreadGroup[] list)

      将该线程组及子线程组中活跃的线程组拷贝至指定的数组。

    • int enumerate​(ThreadGroup[] list, boolean recurse)

      将该线程组及子线程组(可选,recurse为false时只拷贝该线程组中活跃的线程组)中活跃的线程组拷贝至指定的数组。

    • void interrupt()

      中断线程组中所有的线程。

    二.线程工厂

      ThreadFactory接口是Java中的线程工厂,它是工厂模式的一种体现。它定义了如下工厂方法:

    public Thread newThread(Runnable r);
    

      通过自定义线程工厂,我们可以在创建线程时对线程进行一些设置,例如是否是守护线程,统一给线程命名,设置线程优先级,设置线程组等,这使得在创建多个线程时无需手动调用Thread类的构造方法。例如Executors的newFixedThreadPoll(int nThreads, ThreadFactory threadFactory)方法,该方法会返回一个包含固定数量线程的线程池(有关线程池的内容会在后面的文章中介绍),我们可以将线程工厂传递给这个方法,这样线程池在创建线程时就会通过我们的线程工厂的方法去创建。
      例如,下面的线程工厂为每一个线程都设置了统一格式的名字:

    import java.util.concurrent.ThreadFactory;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class MyThreadFactory implements ThreadFactory {
        private static final String THREAD_NAME_PREFIX = "mythread-";
        private static final AtomicInteger THREAD_NUMBER = new AtomicInteger(1);
    
        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, THREAD_NAME_PREFIX + THREAD_NUMBER.getAndIncrement());
        }
    }
    
  • 相关阅读:
    Mac电脑kernel_task占用内存过高
    Mac上的聚焦搜索无法查找到应用
    Mac电脑变卡的原因:
    IE浏览器整页截屏程序
    拓扑排序算法的一个应用
    简单演示mySQL后端数据库关系信息逆向加入到PowerDesigner的物理数据模型和概念数据模型中
    解密存储过程或函数
    C#画图
    .NET设计模式开篇
    非重复随机序列生成算法
  • 原文地址:https://www.cnblogs.com/maconn/p/13744312.html
Copyright © 2020-2023  润新知