线程基础(十二)线程组

线程组

可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的组织结构有点类似于树的形式,如图所示:

 

线程组的作用是:可以批量管理线程或线程组对象,有效地对线程或线程组对象进行组织

 

线程关联线程组: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

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值