Java多线程:线程管理之线程组

培训教学 潘老师 6个月前 (11-10) 123 ℃ (0) 扫码查看

本文重点介绍Java多线程:线程管理之线程组相关知识。Java线程组是一种用于管理线程的机制,类似于在计算机中使用文件夹管理文件,也可以使用线程组来管理线程,在线程组中定义一组相似(相关)的线程。也可以在线程组中定义子线程组。

什么是线程组?

线程组是一个用于组织和管理线程的对象。它可以包含多个线程,将它们组织成一个单元,从而更容易进行管理和控制。线程组有助于将相关线程分组,便于监视和协调它们的行为。

ThreadGroup类的构造函数

Java线程组由java.lang.ThreadGroup类实现。

ThreadGroup类有2个构造函数,其中一个允许你指定线程组的名称和父线程组。

编号 构造函数 描述
1 ThreadGroup(String name) 创建具有给定名称的线程组。
2 ThreadGroup(ThreadGroup parent, String name) 创建具有给定父组和名称的线程组。

如何创建线程组?

要创建线程组,你可以使用ThreadGroup类的构造函数。

代码示例:

ThreadGroup parentGroup = new ThreadGroup("ParentGroup"); // 创建一个名为ParentGroup的线程组
ThreadGroup childGroup = new ThreadGroup(parentGroup, "ChildGroup"); // 创建一个名为ChildGroup的子线程组

在上面的示例中,我们首先创建了一个名为ParentGroup的线程组,然后在该组内创建了一个名为ChildGroup的子线程组。线程组可以形成层级结构,其中子线程组可以包含在父线程组内。

线程组ThreadGroup类的方法

编号 方法 描述
1 void checkAccess() 此方法确定当前运行的线程是否具有修改线程组的权限。
2 int activeCount() 此方法返回线程组及其子组中活动线程数的估计值。
3 int activeGroupCount() 此方法返回线程组及其子组中活动组数量的估计值。
4 void destroy() 此方法会销毁线程组及其所有子组。
5 int enumerate(Thread[] list) 此方法将线程组及其子组中的每个活动线程复制到指定的数组中。
6 int getMaxPriority() 此方法返回线程组的最大优先级。
7 String getName() 此方法返回线程组的名称。
8 ThreadGroup getParent() 此方法返回线程组的父级。
9 void interrupt() 此方法中断线程组中的所有线程。
10 boolean isDaemon() 此方法测试线程组是否为守护程序线程组。
11 void setDaemon(boolean daemon) 此方法更改线程组的守护程序状态。
12 boolean isDestroyed() 此方法测试此线程组是否已被销毁。
13 void list() 此方法将有关线程组的信息打印到标准输出。
14 boolean parentOf(ThreadGroup g) 此方法测试线程组是线程组参数还是其祖先线程组之一。
15 void suspend() 此方法用于挂起线程组中的所有线程。
16 void resume() 此方法用于恢复使用suspend()方法挂起的线程组中的所有线程。
17 void setMaxPriority(int pri) 此方法设置组的最大优先级。
18 void stop() 此方法用于停止线程组中的所有线程。
19 String toString() 此方法返回线程组的字符串表示形式。

获取线程所在线程组

JVM在创建main线程时会为它指定一个线程组,因此每个Java线程都有一个线程组与之关联,可以调用线程的getThreadGroup()方法返回该线程的线程组。

另外,说明下,Thread类有几个构造方法,其中一个允许在创建线程时指定线程组,如果在创建线程时没有指定线程组,则该线程就属于父线程所在的线程组。

public class Test01 {

    public static void main(String[] args) {
        //返回当前main线程的线程组
        ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
//        System.out.println(mainGroup);

        //定义线程组,如果没有指定它的父线程组,那么它就是当前这个线程组的子线程组
        ThreadGroup group1 = new ThreadGroup("group1");
//        System.out.println(group1);
//        System.out.println(group1.getParent());

        //也可以指定父线程组
        ThreadGroup group2 = new ThreadGroup(mainGroup, "group2");
//        System.out.println(group2.getParent());

        //创建线程时指定所属线程组
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread());
            }
        };

        //创建线程时,如果没有指定线程组,默认归属到父线程的线程组中
        //我们在main线程中创建了t线程,所以t线程是main线程的子线程
        //如果t线程没有指定线程组,那么它的线程组就是默认为main线程的线程组
        Thread t = new Thread(r);
        System.out.println(t);

        //创建线程时,可以指定线程所属的线程组
        Thread t2 = new Thread(group1, r, "t2");
        Thread t3 = new Thread(group2, r, "t3");
        System.out.println(t3);
    }
}

复制线程组中的线程及其子线程、获取活动线程数

代码示例:

public class Test03 {

    public static void main(String[] args) {
        ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    TimeUnit.SECONDS.sleep(1000);
                } catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        };

        Thread m1 = new Thread(mainGroup, r);
        Thread m2 = new Thread(mainGroup, r);
        
        ThreadGroup group1 = new ThreadGroup("group1");
        Thread g1 = new Thread(group1, r);
        Thread g2 = new Thread(group1, r);

        m1.start();
        m2.start();
        g1.start();
        g2.start();

        ThreadGroup group2 = new ThreadGroup(group1, "group2");

        Thread[] list = new Thread[mainGroup.activeCount()];
        ThreadGroup[] groupList = new ThreadGroup[mainGroup.activeGroupCount()];
        mainGroup.enumerate(list, false);
        mainGroup.enumerate(groupList, false);

        System.out.println("开始打印");
        System.out.println(list.length);
        System.out.println(groupList.length);
        for(Thread thread : list) {
            System.out.println(thread);
        }

        for(ThreadGroup group : groupList) {
            System.out.println(group);
        }
    }
}

线程组的批量中断

线程组的interrupt()方法可以给线程组中的所有线程添加中断标志。

public class Test04 {

    public static void main(String[] args) throws InterruptedException {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                while(!Thread.interrupted()) {
                    System.out.println(Thread.currentThread().getName() + "is running");
                }
                System.out.println(Thread.currentThread().getName() + "is interrupted");
            }
        };

        ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
        Thread t1 = new Thread(mainGroup, r);
        Thread t2 = new Thread(mainGroup, r);

        ThreadGroup group1 = new ThreadGroup(mainGroup, "g1");
        Thread t3 = new Thread(group1, r);
        Thread t4 = new Thread(group1, r);

        t1.start();
        t2.start();
        t3.start();
        t4.start();

        TimeUnit.SECONDS.sleep(1);
        mainGroup.interrupt();
    }
}

设置守护线程组

守护线程是为其他线程服务的,当JVM中只有守护线程时,守护线程会被销毁,JVM退出。

线程组的setDaemon(true)方法可以把线程组设置为守护线程组,当守护线程组中没有活动线程时,守护线程组被销毁。

守护线程组的守护属性,与其线程的守护属性无关。

挂起和恢复线程组

你可以使用suspend()方法来挂起线程组内的所有线程,使用resume()方法来恢复线程组内的所有线程。这些方法通常用于暂时停止线程组的执行。

注意: 现在不推荐使用suspend()resume()stop()方法。

线程组的销毁

如果你不再需要线程组,可以使用destroy()方法销毁它。销毁线程组将导致线程组内的所有线程停止并被移除。

其他的API方法就不再详细说明,具体参照表格自行研究即可!

线程组的注意事项

  • 线程组并不是线程安全的,因此在线程组内的线程之间共享数据时需要注意同步。
  • 销毁线程组将停止组内的所有线程,请谨慎使用。
  • 线程组的嵌套结构应谨慎设计,以免过度复杂化线程管理。

线程组的常见用法

线程组的任务分组

一个常见的用法是将相关任务分组到不同的线程组中。例如,一个应用程序可能有多个不同的任务,如用户界面、后台任务、网络通信等。你可以为每个任务创建一个独立的线程组,以便更好地管理和监视这些任务。

ThreadGroup uiGroup = new ThreadGroup("UIGroup");
ThreadGroup backgroundGroup = new ThreadGroup("BackgroundGroup");
ThreadGroup networkGroup = new ThreadGroup("NetworkGroup");

定时任务

线程组还可以用于执行定时任务。你可以创建

一个定时任务线程组,然后在该组内创建定时任务线程,以执行特定的定时操作。

ThreadGroup timerGroup = new ThreadGroup("TimerGroup");
TimerTask timerTask = new TimerTask(timerGroup);
timerTask.start();

线程池

线程池通常使用线程组来组织线程。线程池会创建一个线程组来包含池内的所有线程,这样就可以轻松地管理和监视线程池的活动。

ExecutorService executor = Executors.newFixedThreadPool(5);
ThreadGroup threadPoolGroup = executor.getThreadGroup();

线程组的主要作用

  • 组织:将相似或相关的线程放在同一个组内,便于管理。
  • 控制:可以对整个线程组执行操作,如挂起、恢复、中断等。
  • 监视:可以获取线程组的状态信息,如活动线程数、线程组名称等。
  • 安全性:线程组可以用于设置安全性策略,限制组内线程的权限。

总结

以上就是Java多线程:线程管理之线程组的全部内容。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/teach/10967.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】