java 线程组_Java多线程16:线程组

线程组

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

803ec957bfc6262da8a6fa5525faf7c8.png

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

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

所谓1级关联就是父对象中有子对象,但并不创建孙对象。这种情况在开发中很常见,比如创建一些线程时,为了有效对这些线程进行阻止管理,通常情况下是创建一个线程组,然后再将部分线程归属到该组中,以此来对零散的线程对象进行有效的管理。

看一下简单的1级关联的例子:

public class MyThread49 implementsRunnable

{public voidrun()

{try{while (!Thread.currentThread().isInterrupted())

{

System.out.println("ThreadName = " +Thread.currentThread().getName());

Thread.sleep(3000);

}

}catch(InterruptedException e)

{

e.printStackTrace();

}

}

}

public static voidmain(String[] args)

{

MyThread49 mt0= newMyThread49();

MyThread49 mt1= newMyThread49();

ThreadGroup tg= new ThreadGroup("新建线程组1");

Thread t0= newThread(tg, mt0);

Thread t1= newThread(tg, mt1);

t0.start();

t1.start();

System.out.println("活动的线程数为:" +tg.activeCount());

System.out.println("线程组的名称为:" +tg.getName());

}

看一下运行结果:

活动的线程数为:2ThreadName= Thread-1ThreadName= Thread-0线程组的名称为:新建线程组1

ThreadName= Thread-1ThreadName= Thread-0ThreadName= Thread-1ThreadName= Thread-0ThreadName= Thread-1ThreadName= Thread-0

...

控制台上打印出的信息表示线程组中有两个线程,并且打印出了线程组的名称。另外,两个线程无限隔3秒打印,也符合代码预期

线程关联线程组:多级关联

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

多级关联的代码就不写了,简单看一下怎么使用关机关联,查看下JDK API的ThreadGroup构造方法:

07cf2792207f782287bb44325a6ae293.png

注意一下第二个,假如要使用多级关联一般就是用第二个构造函数。第一个参数表示新线程组的父线程组,第二个参数表示新线程组的名称,有了父线程组和新线程组的名称,自然可以构造出一个新的线程组来了。

当然用第一个构造方法也是可以的,下一部分就会提到。

另外注意一点,线程必须启动后才能归到指定线程组中。

线程组自动归属特性

自动归属的意思就是自动归到当前线程组中,看一下例子:

public static voidmain(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= newThreadGroup[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 voidmain(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 com.xrq.example.e49.TestMain49.main(TestMain49.java:11)

运行结果可以得出两个结论:

1、根线程组就是系统线程组system

2、抛空指针异常是因为系统线程组上已经没有线程组了,所以system的getParent()方法返回的是null,对null调用getName()方法自然是NullPointerException

关于根线程组,看一下ThreadGroup的源码:

/*** 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;

}

一个私有构造方法,说明不是对开发者开放的。注释上已经写得很清楚了,这是C代码调用的,用于构建系统线程组。

批量停止组内线程

使用线程组自然是要对线程做批量管理的,到目前为止我们似乎都没有看见如何对线程组内的线程做批量操作,最后来看一下批量操作线程组内的线程:

public class MyThread50 extendsThread

{publicMyThread50(ThreadGroup tg, String name)

{super(tg, name);

}public voidrun()

{

System.out.println("ThreadName = " + Thread.currentThread().getName() +

"准备开始死循环了");while (!this.isInterrupted()){}

System.out.println("ThreadName = " + Thread.currentThread().getName() +

"结束了");

}

}

开3个线程:

public static void main(String[] args) throwsInterruptedException

{

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=线程2结束了

ThreadName=线程1结束了

ThreadName=线程0结束了

看到调用了ThreadGroup中的interrupt()方法批量中断了线程组内的线程,这就是ThreadGroup的作用。更多线程组的操作可以查看JDK API。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值