Java并发编程:认识线程组
来源:互联网 发布:朝鲜人眼中的中国知乎 编辑:程序博客网 时间:2024/06/04 01:15
可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的组织结构有点类似于树的形式,如图所示:
线程组的作用是:可以批量管理线程或线程组对象,有效地对线程或线程组对象进行组织。
一、线程关联线程组:1级关联
所谓1级关联就是父对象中有子对象,但并不创建孙对象。这种情况在开发中很常见,比如创建一些线程时,为了有效对这些线程进行组织管理,通常情况下是创建一个线程组,然后再将部分线程归属到该组中,以此来对零散的线程对象进行有效的管理。
package com.mook.threadGroup;class MyThread49 implements Runnable{ public void run() { try { while (!Thread.currentThread().isInterrupted()) { System.out.println("ThreadName = " + Thread.currentThread().getName()); Thread.sleep(3000); } } catch (InterruptedException e) { e.printStackTrace(); } }}public class Test { public static void main(String[] args) { MyThread49 mt0 = new MyThread49(); MyThread49 mt1 = new MyThread49(); ThreadGroup tg = new ThreadGroup("新建线程组1"); Thread t0 = new Thread(tg, mt0); Thread t1 = new Thread(tg, mt1);// System.out.println("活动的线程数为:" + tg.activeCount()); //0 t0.start(); t1.start(); System.out.println("活动的线程数为:" + tg.activeCount()); System.out.println("线程组的名称为:" + tg.getName()); }}
线程必须启动后才能归到指定线程组中。
活动的线程数为:2ThreadName = Thread-1ThreadName = Thread-0线程组的名称为:新建线程组1ThreadName = Thread-0ThreadName = Thread-1ThreadName = Thread-0ThreadName = Thread-1ThreadName = Thread-0ThreadName = Thread-1ThreadName = Thread-0ThreadName = Thread-1...
二、线程关联线程组:多级关联
所谓的多级关联就是父对象中有子对象,子对象中再创建子对象买也就出现了子孙的效果了。但是这种写法在开发中不太常见,因为线程树如果涉及得复杂反而不利于线程对象的管理,不过JDK确实提供了多级关联的线程树结构。
public ThreadGroup(String name) { this(Thread.currentThread().getThreadGroup(), name); }
public ThreadGroup(ThreadGroup parent, String name) { this(checkParentAccess(parent), parent, name); }
第一个参数表示新线程组的父线程组,第二个参数表示新线程组的名称,有了父线程组和新线程组的名称,自然可以构造出一个新的线程组来了。
三、线程组自动归属特性
自动归属的意思就是自动归到当前线程组中,看一下例子:
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, 组中有线程组数量:0B处线程:main, 所属线程:main, 组中有线程组数量:1第一个线程组名称为:新的组
实例化了一个group出来,没有指定线程组,那么自动归到当前线程所属的线程组中,也就是隐式地在一个线程组中添加了一个子线程组。
四、根线程组
public static void main(String[] args){ System.out.println(Thread.currentThread().getThreadGroup().getParent().getName()); System.out.println(Thread.currentThread().getThreadGroup().getParent().getParent().getName());}
systemException in thread "main" java.lang.NullPointerException at com.xrq.example.e49.TestMain49.main(TestMain49.java:11)
运行结果可以得出两个结论:
1、根线程组就是系统线程组system
2、抛空指针异常是因为系统线程组上已经没有线程组了,所以system的getParent()方法返回的是null,对null调用getName()方法自然是NullPointerException
/** * 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; }
一个私有构造方法,说明不是对开发者开放的。注释上已经写得很清楚了,这是C代码调用的,用于构建系统线程组。
五、批量停止组内线程
使用线程组自然是要对线程做批量管理的
package com.mook.threadGroup;class MyThread50 extends Thread{ public MyThread50(ThreadGroup tg, String name) { super(tg, name); } public void run() { System.out.println("ThreadName = " + Thread.currentThread().getName() + "准备开始死循环了"); while (!this.isInterrupted()){} System.out.println("ThreadName = " + Thread.currentThread().getName() + "结束了"); }}public class Test2 { public static void main(String[] args) throws InterruptedException { ThreadGroup tg = new ThreadGroup("我的线程组"); MyThread50 mt = null; for (int i = 0; i < 3; i++) { mt = new MyThread50(tg, "线程" + i); mt.start(); } Thread.sleep(5000); tg.interrupt(); System.out.println("调用了interrupt()方法"); }}
ThreadName = 线程0准备开始死循环了ThreadName = 线程2准备开始死循环了ThreadName = 线程1准备开始死循环了调用了interrupt()方法ThreadName = 线程0结束了ThreadName = 线程1结束了ThreadName = 线程2结束了
看到调用了ThreadGroup中的interrupt()方法批量中断了线程组内的线程,这就是ThreadGroup的作用。更多线程组的操作可以查看JDK API。
- Java并发编程:认识线程组
- Java并发编程笔记(1):初步认识并发、并行、进程、线程
- java编程思想之并发(认识多线程)
- Java并发编程(2)-线程
- java并发编程:线程池
- Java并发编程:线程创建
- Java并发编程:线程池
- Java并发编程 线程池
- java并发编程---线程池
- java并发编程:线程让步
- Java并发编程:线程池
- java并发编程:线程安全性
- java线程高并发编程
- Java并发编程-线程安全性
- Java并发编程:线程池
- 【Java并发编程】线程池
- 【java】【并发编程】线程封闭
- Java线程进行并发编程
- ORACLE笔记二
- 获取js异步函数的返回值
- springmvc和DWR的整合
- 并发(一):理解可重入锁
- Struts2 介绍和应用
- Java并发编程:认识线程组
- Hive自定义UDF和聚合函数UDAF
- 关于Installation failed的情况及解决方案
- Git常用命令
- 初识小波变换(一)
- 浅谈Three.js源码-render之WebGLBackground.js
- okhttp3.0使用https访问网络
- 如何使用IntentService
- ajax的beforeSend 提交等待问题 (ajaxSubmit相同)