线程组
可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的组织结构有点类似于树的形式,如图所示:
线程组的作用是:可以批量管理线程或线程组对象,有效地对线程或线程组对象进行组织。
线程关联线程组:1级关联
所谓1级关联就是父对象中有子对象,但并不创建孙对象。这种情况在开发中很常见,比如创建一些线程时,为了有效对这些线程进行阻止管理,通常情况下是创建一个线程组,然后再将部分线程归属到该组中,以此来对零散的线程对象进行有效的管理。
public class Test01 {
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
while(true){
System.out.println("Thread-Name:"+Thread.currentThread().getName());
Thread.sleep(3000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
ThreadGroup tg = new ThreadGroup("线程组1");
Thread t1 = new Thread(tg,r,"线程1");
Thread t2 = new Thread(tg,r,"线程2");
t1.start();
t2.start();
System.out.println("当前线程组名称:"+tg.getName());
System.out.println("当前线程组活动线程有:"+tg.activeCount());
}
}
当前线程组名称:线程组1
当前线程组活动线程有:2
Thread-Name:线程2
Thread-Name:线程1
Thread-Name:线程1
Thread-Name:线程2
控制台上打印出的信息表示线程组中有两个线程,并且打印出了线程组的名称。
线程关联线程组:多级关联
所谓的多级关联就是父对象中有子对象,子对象中再创建子对象买也就出现了子孙的效果了。但是这种写法在开发中不太常见,因为线程树如果涉及得复杂反而不利于线程对象的管理,不过JDK确实提供了多级关联的线程树结构。
注意一下第二个,假如要使用多级关联一般就是用第二个构造函数。第一个参数表示新线程组的父线程组,第二个参数表示新线程组的名称,有了父线程组和新线程组的名称,自然可以构造出一个新的线程组来了。
当然用第一个构造方法也是可以的,下一部分就会提到。
另外注意一点,线程必须启动后才能归到指定线程组中。
public class Test02 {
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
while(true){
System.out.println("Thread-Name:"+Thread.currentThread().getName());
Thread.sleep(3000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
ThreadGroup tg = new ThreadGroup("线程组1");
Thread t1 = new Thread(tg,r,"线程1");
Thread t2 = new Thread(tg,r,"线程2");
ThreadGroup tg1 = new ThreadGroup(tg,"线程组2");
t1.start();
t2.start();
System.out.println("当前线程组名称:"+tg.getName());
System.out.println("当前线程组活动线程有:"+tg.activeCount());
System.out.println("当前线程组活动线程组有:"+tg.activeGroupCount());
System.out.println("当前线程组活动线程组父线程组:"+tg.getParent());
System.out.println("当前线程组名称:"+tg1.getName());
System.out.println("当前线程组活动线程有:"+tg1.activeCount());
System.out.println("当前线程组活动线程组有:"+tg1.activeGroupCount());
System.out.println("当前线程组活动线程组父线程组:"+tg1.getParent());
}
}
Thread-Name:线程1
Thread-Name:线程2
当前线程组名称:线程组1
当前线程组活动线程有:2
当前线程组活动线程组有:1
当前线程组活动线程组父线程组:java.lang.ThreadGroup[name=main,maxpri=10]
当前线程组名称:线程组2
当前线程组活动线程有:0
当前线程组活动线程组有:0
当前线程组活动线程组父线程组:java.lang.ThreadGroup[name=线程组1,maxpri=10]
Thread-Name:线程1
Thread-Name:线程2
线程组自动归属特性
自动归属的意思就是自动归到当前线程组中
public class Test03 {
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
while(true){
System.out.println("Thread-Name:"+Thread.currentThread().getName());
Thread.sleep(3000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t1 = new Thread(r,"线程1");
Thread t2 = new Thread(r,"线程2");
t1.start();
t2.start();
System.out.println("当前线程为"+Thread.currentThread().getName());
System.out.println("线程1的线程组是"+t1.getThreadGroup().getName());
System.out.println("线程1的线程组当前有"+t1.getThreadGroup().activeCount()+"个活动线程");
System.out.println("线程2的线程组是"+t2.getThreadGroup().getName());
System.out.println("线程2的线程组当前有"+t2.getThreadGroup().activeCount()+"个活动线程");
}
}
Thread-Name:线程1
当前线程为main
Thread-Name:线程2
线程1的线程组是main
线程1的线程组当前有3个活动线程
线程2的线程组是main
线程2的线程组当前有3个活动线程
Thread-Name:线程1
Thread-Name:线程2
从结果看出,当前线程组为main线程组,当前线程为main,线程1和线程2会自动归属到当前线程组main中
根线程组
public class Test04 {
public static void main(String[] args) {
System.out.println(Thread.currentThread()
.getThreadGroup().getParent().getName());
System.out.println(Thread.currentThread()
.getThreadGroup().getParent().getParent().getName());
}
}
system
Exception in thread "main" java.lang.NullPointerException
at c_threadgroup.Test04.main(Test04.java:8)
运行结果可以得出两个结论:
1、根线程组就是系统线程组system
2、抛空指针异常是因为系统线程组上已经没有线程组了,所以system的getParent()方法返回的是null,对null调用getName()方法自然是NullPointerException
批量停止组内线程
public class Test05 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"开始死循环");
while(!Thread.currentThread().isInterrupted()){
}
System.out.println(Thread.currentThread().getName()+"死循环结束");
}
public static void main(String[] args) {
Test05 t = new Test05();
ThreadGroup tg = new ThreadGroup("新建线程组");
Thread t1 = new Thread(tg, t, "线程1");
Thread t2 = new Thread(tg, t, "线程2");
Thread t3 = new Thread(tg, t, "线程3");
t1.start();
t2.start();
t3.start();
try {
Thread.sleep(5000);
tg.interrupt();
System.out.println("调用了interrupt()方法");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
线程2开始死循环
线程3开始死循环
线程1开始死循环
调用了interrupt()方法
线程3死循环结束
线程1死循环结束
线程2死循环结束
看到调用了ThreadGroup中的interrupt()方法批量中断了线程组内的线程,这就是ThreadGroup的作用。更多线程组的操作可以查看JDK API