拾遗增补(二)——线程组

  可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的组织结构有点类似于树的形式,如图所示:
在这里插入图片描述
  线程组的作用是:可以批量管理线程或线程组对象,有效地对线程或线程组对象进行组织。

1.线程关联线程组:1级关联

  所谓1级关联就是父对象中有子对象,但并不创建子孙对象。这种情况经常出现在开发中,比如创建一些线程时,为了有效对这些线程进行阻止管理,通常情况下是创建一个线程组,然后再将部分线程归属到该组中。这样的处理可以对零散的线程对象进行有效的组织与规划。
  创建名称为7.2.1的项目。
  创建两个线程类,如下
类ThreadA.java代码如下:

public class ThreadA extends Thread {
    @Override
    public void run() {
        super.run();
        try {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("Thread name : " + Thread.currentThread().getName());
                Thread.sleep(3000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

类ThreadB.java代码如下:

public class ThreadB extends Thread {
    @Override
    public void run() {
        super.run();
        try {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("Thread name : " + Thread.currentThread().getName());
                Thread.sleep(3000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

创建运行类Run.java代码如下:

public class Run {
    public static void main(String[] args) {
        ThreadA aRunnable = new ThreadA();
        ThreadB bRunnable = new ThreadB();
        ThreadGroup group = new ThreadGroup("线程组");
        Thread aThread = new Thread(group, aRunnable);
        Thread bThread = new Thread(group, bRunnable);
        aThread.start();
        bThread.start();
        System.out.println("活动的线程数 : " + group.activeCount());
        System.out.println("线程组的名称 : " + group.getName());
    }
}

程序运行后的结果如下所示:

活动的线程数 : 2
Thread name : Thread-2
Thread name : Thread-3
线程组的名称 : 线程组
Thread name : Thread-2
Thread name : Thread-3
Thread name : Thread-2
Thread name : Thread-3
Thread name : Thread-2
Thread name : Thread-3
Thread name : Thread-2
Thread name : Thread-3

  控制台中打印的信息表示线程组中有两个线程,并且打印出了线程组的名称。另外,两个线程一直无限地并且每隔3秒打印日志。

2.线程对象关联线程组:多级关联

  所谓的多级关联就是父对象中有子对象,子对象中再创建子对象,也就出现了子孙的效果了。但是这种写法在开发中不太常见,因为线程树如果涉及得复杂反而不利于线程对象的管理,不过JDK确实提供了多级关联的线程树结构。
  创建名称为7.2.2的项目。
  创建运行类Run.java代码如下:

public class Run {
    public static void main(String[] args) {
        //再main组中添加一个线程组A,然后在这个A组中添加线程对象Z
        //方法acativeGroupCount()和activeCount()的值不是固定的
        //是系统中环境的一个快照
        ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
        ThreadGroup group = new ThreadGroup(mainGroup, "A");
        Runnable runnable = new Runnable() {

            @Override
            public void run() {
                try {
                    System.out.println("run method");
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        Thread newThread = new Thread(group, runnable);
        newThread.setName("Z");
        newThread.start();//线程必须启动然后才归到A中
        ThreadGroup[] listGroup = new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];
        Thread.currentThread().getThreadGroup().enumerate(listGroup);
        System.out.println("main线程中有多少个线程组:" + listGroup.length + "个子线程,名字:" + listGroup[0].getName());
        Thread[] listThread = new Thread[listGroup[0].activeCount()];
        listGroup[0].enumerate(listThread);
        System.out.println(listThread[0].getName());
    }
}

  程序运行结果如下所示。

main线程中有多少个线程组:1个子线程,名字:A
run method
Z

运行结果

  本程序代码的结构就是main组创建一个新组,然后又在该新组中添加了线程。

3.线程组自动归属特性

  自动归属就是自动归到当前线程组中。
  创建名称为7.2.3项目。
  创建运行类Run.java代码如下:

public class Run {
    public static void main(String[] args)
    {
        System.out.println("A处线程:" + Thread.currentThread().getName() + ", 所属线程:" + Thread.currentThread().getThreadGroup().getName() +
                ", 组中有线程组数量:" + Thread.currentThread().getThreadGroup().activeGroupCount());
        ThreadGroup group = new ThreadGroup("新的组");
        System.out.println("B处线程:" + Thread.currentThread().getName() + ", 所属线程:" + Thread.currentThread().getThreadGroup().getName() +
                ", 组中有线程组数量:" + Thread.currentThread().getThreadGroup().activeGroupCount());
        ThreadGroup[] tg = new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];
        Thread.currentThread().getThreadGroup().enumerate(tg);
        for (int i = 0; i < tg.length; i++)
            System.out.println("第一个线程组名称为:" + tg[i].getName());
    }
}

  程序运行后的结果如下所示:

A处线程:main, 所属线程:main, 组中有线程组数量:0
B处线程:main, 所属线程:main, 组中有线程组数量:1
第一个线程组名称为:新的组

  本实验要证明的是,在实例化一个ThreadGroup线程组x时如果不指定所属的线程组,则x线程组自动归到当前线程对象所属的线程组中,也就是隐式地在一个线程组中添加了一个子线程组,所以在控制台中打印的线程组数量值由0变成了1。

4.获取根线程组

  创建名称为7.2.4项目。
  创建运行类Run.java代码如下:

public class Run {
    public static void main(String[] args)
    {
        System.out.println("线程:" + Thread.currentThread().getName() + "所在的线程组名为:"
        + Thread.currentThread().getThreadGroup().getName());
        System.out.println("main线程所在的线程组的父线程组的名称是:" +
                Thread.currentThread().getThreadGroup().getParent().getName());
        System.out.println("main线程所在的线程组的父线程组的父线程组的名称是:" +
                Thread.currentThread().getThreadGroup().getParent().getParent().getName());
    }
}

  程序运行后的结果如下所示:

线程:main所在的线程组名为:main
main线程所在的线程组的父线程组的名称是:system
Exception in thread "main" java.lang.NullPointerException
	at Run.main(Run.java:9)

  运行结果说明JVM 的根线程组就是 system,再取其父线程组则出现空异常。

5.线程组里加线程组

  创建名称为7.2.5项目。
  创建运行类Run.java代码如下:

public class Run {
    public static void main(String[] args) {
    System.out.println("线程组名称:"
            + Thread.currentThread().getThreadGroup().getName());
    System.out.println("线程组中活动的线程数量:"
            + Thread.currentThread().getThreadGroup().activeCount());
    System.out.println("线程组中线程组的数量-加之前:"
            + Thread.currentThread().getThreadGroup().activeGroupCount());
    new ThreadGroup(Thread.currentThread().getThreadGroup(), "newGroup");
    System.out.println("线程组中线程组数量-加之后:"
            + Thread.currentThread().getThreadGroup().activeGroupCount());
    System.out.println("父线程组名称:"
            + Thread.currentThread().getThreadGroup().getParent().getName());
}
}

  程序运行后的结果如下所示:

线程组名称:main
线程组中活动的线程数量:2
线程组中线程组的数量-加之前:0
线程组中线程组数量-加之后:1
父线程组名称:system

  本实验用显式的方式在一个线程组中添加了一个线程组。

6.组内的线程的批量停止

  创建名称为7.2.6项目。
  创建MyThread.java类代码如下:

public class MyThread extends Thread{
    public MyThread(ThreadGroup group, String name){
        super(group, name);
    }
    @Override
    public void run() {
        System.out.println("ThreadName=" + Thread.currentThread()
                .getName() + "准备开始死循环了:)");
        while (!this.isInterrupted()) {
        }
        System.out.println("ThreadName=" + Thread.currentThread().getName()
                +"结束了:)");
    }
}

  创建运行类Run.java代码如下:

public class Run {
    public static void main(String[] args) {
        try {
            ThreadGroup group = new ThreadGroup("我的线程组");
            for (int i = 0; i < 5; i++) {
                MyThread thread = new MyThread(group, "线程" + (i + 1));
                thread.start();
            }
            Thread.sleep(5000);
            group.interrupt();
            System.out.println("调用了interrupt()方法");
        } catch (InterruptedException e) {
            System.out.println("停了!");
            e.printStackTrace();
        }
    }
}

  程序运行后的结果如下所示:

ThreadName=线程2准备开始死循环了:)
ThreadName=线程1准备开始死循环了:)
ThreadName=线程5准备开始死循环了:)
ThreadName=线程3准备开始死循环了:)
ThreadName=线程4准备开始死循环了:)
调用了interrupt()方法
ThreadName=线程2结束了:)
ThreadName=线程3结束了:)
ThreadName=线程4结束了:)
ThreadName=线程5结束了:)
ThreadName=线程1结束了:)

  通过将线程归属到线程组中,当调用线程组 ThreadGroup 的 interrupted() 方法时,可以将该组中的所有正在运行的线程批量停止。

7.递归与非递归取得组内对象

  创建名称为7.2.7项目。
  创建运行类Run.java代码如下:

public class Run {
    public static void main(String[] args) {
        ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
        ThreadGroup groupA = new ThreadGroup(mainGroup, "A");
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("runMethod!");
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        ThreadGroup groupB = new ThreadGroup(groupA, "B");
        //分配空间,但不一定全部用完
        ThreadGroup[] listGroup1 = new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];
        //传入true是递归取得子组及子孙组
        Thread.currentThread().getThreadGroup().enumerate(listGroup1,true);
        for (int i = 0; i < listGroup1.length; i++) {
            if (null != listGroup1[i]) {
                System.out.println(listGroup1[i].getName());
            }
        }
        ThreadGroup[] listGroup2 = new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];
        //传入true是递归取得子组及子孙组
        Thread.currentThread().getThreadGroup().enumerate(listGroup2,false);
        for (int i = 0; i < listGroup2.length; i++) {
            if (null != listGroup2[i]) {
                System.out.println(listGroup2[i].getName());
            }
        }
    }
}

  程序运行后的结果如下所示:

A
B
A


以上代码下载请点击该链接:https://github.com/Yarrow052/Java-package.git

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值