助力软件开发企业降本增效 PHP / java源码系统,只需一次付费,代码终身使用! 广告
# ThreadGroup API介绍 TreadGroup其实是在1.5之前用的比较多,在没有线程池API前都使用TreadGroupApi来管理线程池。虽然现在有线程池API来供大家使用,但是如果在平时开发中只想启用三五个线程,那么可以选择使用TreadGroup来管理线程。 我们找到ThreadGroup来看一下: ![](https://img.kancloud.cn/25/e4/25e41ab9d98756206dfd4eb83861f5bc_1040x196.png) 线程组表示一组线程。此外,线程组还可以包括其他线程组。线程组形成一个树,其中除了初始线程组外,每个线程组都有一个父线程组。 允许线程访问关于其自己线程组的信息,但不允许访问关于其线程组的父线程组或任何其他线程组的信息。 那么,允许线程访问关于其自己线程组的信息的信息都是什么呢?我们接下来看一下: 首先创建一个threadgroup ```java public class ThreadGroupCreate { public static void main(String[] args) { // 1. use the name ThreadGroup tg1 = new ThreadGroup("TG1"); Thread t1 = new Thread(tg1, () -> { while (true) { try { Thread.sleep(10_000); } catch (InterruptedException e) { e.printStackTrace(); } } }, "T1"); t1.start(); System.out.println("t1's thread group name = " + t1.getThreadGroup().getName());// TG1 //todo 2. use the parent and group name } } ``` 运行效果如下: ![](https://img.kancloud.cn/b5/cf/b5cf77e79d3a6e7734ee4c1264046ac9_856x228.gif) 打印一下当前threadgroup的名字和他父级的名字: ```java ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); System.out.println(threadGroup.getName()); System.out.println(threadGroup.getParent()); ``` 运行效果如下: ![](https://img.kancloud.cn/c8/f5/c8f53b73fd473c9eec218da2795a0fa2_856x210.gif) 可以看到他的线程组是TG1,他的夫级线程组是main,并且main线程的优先级很高是10。 接下来我们给创建另一个线程组,他的夫级线程组TG1: ```java //2. use the parent and group name ThreadGroup tg2 = new ThreadGroup(tg1, "TG2"); System.out.println("tg2's name = " + tg2.getName()); System.out.println("tg2's parent name = " + tg2.getParent().getName()); ``` 运行效果如下: ![](https://img.kancloud.cn/57/63/5763b80196fb7bf2cd42b4318f796118_856x210.gif) 线程组两种创建方式就ok了,我们再来验证一下:**允许线程访问关于其自己线程组的信息,但不允许访问关于其线程组的父线程组或任何其他线程组的信息**。 ```java //TG2 访问TG1 ThreadGroup tg2 = new ThreadGroup(tg1, "TG2"); Thread t2 = new Thread(tg2,()->{ System.out.println("tg2's parent threadgroup is"+tg2.getName()); }); t2.start(); // TG3与TG1为同一个父ThreadGroup-main // 测试TG3能否访问TG1的一些信息 ThreadGroup tg3 = new ThreadGroup("TG3"); Thread t3 = new Thread(tg3, () -> { System.out.println(">>>>" + t1.getName());// TG1 Thread[] threads = new Thread[tg1.activeCount()]; tg1.enumerate(threads); Stream.of(threads).forEach(System.out::println);// Thread[T1,5,TG1] }, "T3"); t3.start(); ``` 运行效果如下: 可以看到其实是可以访问的,可能是官方文档有问题,也有可能是我翻译的有问题。。。 ## 接下来学习几个ThreadGroup的常用方法: #### activeCount() ![](https://img.kancloud.cn/17/e6/17e66efebb2e29ff25be745fb9686c34_936x74.png) 返回此线程组及其子组中活动线程的评估数量。这里注意是评估数量,因为可能获取的时候,某个线程消亡了或者正在被添加。 ```java public class ThreadGroupAPI { public static void main(String[] args) { ThreadGroup tg1 = new ThreadGroup("TG1"); Thread t1 = new Thread(tg1, () -> { while (true) { try { Thread.sleep(1_000); } catch (InterruptedException e) { e.printStackTrace(); break; } } }, "T1"); /*tg1.setDaemon(true);*/ t1.start(); ThreadGroup tg2 = new ThreadGroup(tg1, "TG2"); Thread t2 = new Thread(tg2, () -> { while (true) { try { Thread.sleep(1_000); } catch (InterruptedException e) { e.printStackTrace(); break; } } }, "T2"); t2.start(); System.out.println("tg1 active count is " + tg1.activeCount()); } } ``` 运行效果如下: ![](https://img.kancloud.cn/2d/d5/2dd551cec66963b7a1b5f4657b408b0c_856x204.gif) #### activeGroupCount() ![](https://img.kancloud.cn/d8/ad/d8adf4dfa87bf6c32bb9da1856d72370_988x73.png) 返回此线程组及其子组中活动组的评估数量。 ```java System.out.println(tg1.activeGroupCount()); ``` 运行效果如下: ![](https://img.kancloud.cn/41/c4/41c4fdaa7e6069e839688e97de7b84b6_856x204.gif) #### checkAccess() ![](https://img.kancloud.cn/ec/86/ec86f140dcc70baa88c448b81b36c80b_974x183.png) 确定当前运行的线程是否具有修改此线程组的权限。 代码如下: ```java tg1.checkAccess(); ``` 运行效果如下: ![](https://img.kancloud.cn/73/c0/73c0aed27de40a0d0500f7a3ddb2bbef_856x204.gif) 没抛出异常代表有权限修改线程组。 #### destroy() ![](https://img.kancloud.cn/4e/7f/4e7fcb1d5631be321c7879745d7f09bc_1001x358.png) 销毁这个线程组及其所有子组。destroy前需要确定线程组里没有活跃的线程。如果线程组不为空或线程组已被销毁将抛出`IllegalThreadStateException` 代码如下: ```java tg1.destroy(); ``` 运行效果如下: ![](https://img.kancloud.cn/cf/f8/cff8748ac36a557d497ee06eaecdd489_856x204.gif) 因为我们线程里有while,所以是活跃的线程,这里就抛出异常了。 #### enumerate(Thread[] list) ![](https://img.kancloud.cn/e0/9e/e09e82ceef838da81735587a37052198_1007x63.png) 将此线程组及其子组中的每个活动线程复制到指定的数组中。 代码如下: ```java Thread[] ts1 = new Thread[tg1.activeCount()]; tg1.enumerate(ts1); System.out.println(Arrays.toString(ts1)); ``` 运行效果如下: ![](https://img.kancloud.cn/83/77/837708808a254e70da07d5fefcc9eaa0_856x204.gif) #### enumerate(Thread[] list, boolean recurse) ![](https://img.kancloud.cn/65/42/6542dd63177dab38570e94f03b74844a_989x59.png) 将此线程组中的每个活动线程复制到指定数组中。 代码如下: ```java Thread[] ts2 = new Thread[tg1.activeCount()]; tg1.enumerate(ts2, false); System.out.println(Arrays.toString(ts2)); ``` 运行效果如下: ![](https://img.kancloud.cn/27/8a/278ae01318a672e540c5a5c1d26a8306_856x204.gif) ![](https://img.kancloud.cn/f3/27/f3279d4eb8de00be721f15cb3a1e7b7e_695x89.png) 如果为真,则递归枚举此线程组的所有子组。那么我们使用false试试: ```java ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup(); Thread[] ts3 = new Thread[mainThreadGroup.activeCount()]; mainThreadGroup.enumerate(ts3, false); System.out.println(Arrays.toString(ts3)); ``` 运行效果如下: ![](https://img.kancloud.cn/06/93/0693469c5f2090606ad1784b4141a75c_856x204.gif) #### interrupt() ![image-20200919161631996](23.ThreadGroup API介绍.assets/image-20200919161631996.png) 中断此线程组中的所有线程。 代码如下: ```java tg1.interrupt(); ``` 运行效果如下: ![](https://img.kancloud.cn/e8/43/e8434754e9fe1973313a4b749c21aefc_856x204.gif) #### setDaemon(boolean daemon) ![](https://img.kancloud.cn/74/42/744241563a82d74a95162876b5e4317b_977x337.png) 守护进程——如果为真,则将此线程组标记为守护线程组;否则,将此线程组标记为normal。 ```java ThreadGroup tg1 = new ThreadGroup("TG1"); Thread t1 = new Thread(tg1, () -> { try { Thread.sleep(1_000); } catch (InterruptedException e) { e.printStackTrace(); } }, "T1"); tg1.setDaemon(true); t1.start(); Thread.sleep(2_000); System.out.println(tg1.isDestroyed()); ``` 运行效果如下: ![](https://img.kancloud.cn/72/08/72085452b18ce08afd6cf263c5c29281_856x204.gif) 注释tg1.setDaemon(true);试一下: ![](https://img.kancloud.cn/f4/65/f4658dada63c8fd5fe6ce065a98d442b_856x204.gif) 手动销毁一下: ```java ThreadGroup tg1 = new ThreadGroup("TG1"); Thread t1 = new Thread(tg1, () -> { try { Thread.sleep(1_000); } catch (InterruptedException e) { e.printStackTrace(); } }, "T1"); //tg1.setDaemon(true); t1.start(); Thread.sleep(2_000); System.out.println(tg1.isDestroyed()); tg1.destroy(); System.out.println(tg1.isDestroyed()); ``` 运行效果如下: ![](https://img.kancloud.cn/e8/3f/e83f109c12355e772e73c497d6356327_856x204.gif) 这篇随笔是我周六没吃早饭没吃午饭弄到下午4点38才弄完的,中间多少次想休息一会吃个饭再继续弄,但是还是想弄完了再好好吃饭,也许这样下去永远都胖不起来吧。。。