Java里的线程是可以归属到线程组中的,线程组中可以有线程,也可以有线程组,这种结构有点像树的形式。线程组可以批量化的管理线程或者线程对象,可以更好的组织线程。
线程对象关联线程组:一级关联
一级关联的意思就是线程组中有子线程,但是不会在线程组中创建子线程组。在开发中经常用到这种模式,在创建一些零散的线程时,为了将它们有效的进行组织管理,我们会创建一个线程组,然后把这些零散的线程归属到这个线程组里。我先用一段代码来示例。
class ThreadA extends Thread{
@Override
public void run() {
try{
while(!Thread.currentThread().isInterrupted()){
System.out.println("ThreadName = "+Thread.currentThread().getName()+" 所在的线程组是:"+Thread.currentThread().getThreadGroup().getName());
Thread.sleep(1500);
}
}catch (InterruptedException i){
i.printStackTrace();
}
}
}
class ThreadB extends Thread{
@Override
public void run() {
try{
while (!Thread.currentThread().isInterrupted()){
System.out.println("ThreadName = "+Thread.currentThread().getName()+" 所在的线程组是:"+Thread.currentThread().getThreadGroup().getName());
Thread.sleep(1500);
}
}catch (InterruptedException i){
i.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
ThreadA threadA = new ThreadA();
ThreadB threadB = new ThreadB();
ThreadGroup group = new ThreadGroup("我的线程组");
new Thread(group,threadA).start();
new Thread(group,threadB).start();
System.out.println("正在运行的线程数为 "+group.activeCount());
System.out.println("正在运行的线程组为 "+group.getName());
}
}
输出结果是:
我们可以看出线程组中有两个线程,并且这两个线程只要不被终止就会一直打印信息。
另外,线程必须在处于运行状态时才会受线程组的管理。
线程对象关联线程组:多级关联
多级关联的意思就是线程组中子线程组,子线程中还有子线程组。虽然这种情况在开发中不常见,因为线程树结构应该是越简单越好,如果结构过于复杂反而不利于线程对象的管理。JDK提供了多级关联的结构,我用代码示例一下。
public class Main{
public static void main(String[] args){
ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();//获取main线程组
ThreadGroup group = new ThreadGroup(mainGroup,"A");//创建新的线程组A,放在main线程组里
Runnable runnable = ()->{//要放在线程组A中的线程
try{
System.out.println("New Thread's method");
Thread.sleep(1500);
}catch (InterruptedException i){
i.printStackTrace();
}
};
Thread NewThread = new Thread(group,runnable);
NewThread.setName("New Thread");//创建新的线程并起名为Z
NewThread.start();//线程必须启动才会被放到线程组里
ThreadGroup[] threadGroups = new ThreadGroup[Thread.currentThread().getThreadGroup().activeGroupCount()];//创建ThreadGroup数组,用来存放main线程组中的子线程组
Thread.currentThread().getThreadGroup().enumerate(threadGroups);//将当前线程中的子线程组(线程组A)以复制的形式放到上面创建的ThreadGroup数组中
System.out.println("main线程中子线程组个数是: "+threadGroups.length+" 名字是:"+threadGroups[0].getName());//输出
Thread[] listThread = new Thread[threadGroups[0].activeCount()];//和上面差不多,创建Thread数组,用来存放线程组A中的线程
threadGroups[0].enumerate(listThread);//复制线程组A中的线程到Thread[]数组中
System.out.println("线程组A中的线程名字是: "+listThread[0].getName());
}
}
先看结果
我先介绍几个方法
activeGroupCount();取得当前线程组中的子线程组个数
activeCount();取得当前线程组中子线程个数
enumerate();将当前线程组中的子线程组/线程以复制的方式拷贝到ThreadGroup[]/Thread[]中。
这段代码就是在main线程组里加了一个新线程组A,然后在子线程组A中增加了一个新的线程New_Thread。
线程组的自动归属
如果我们新创建了一个线程组,但是并没有注明它被归属到哪个线程组里。那么该线程组的归属应该是什么呢?先看一段代码。
public class Main {
public static void main(String[] args) {
ThreadGroup maingroup = Thread.currentThread().getThreadGroup();//获得main线程组
System.out.println("main线程组中的子线程组个数: "+maingroup.activeGroupCount());
ThreadGroup threadGroup = new ThreadGroup("子线程组");
System.out.println("main线程组中的子线程组个数: "+maingroup.activeGroupCount());
ThreadGroup[] threadGroups = new ThreadGroup[maingroup.activeGroupCount()];//创建ThreadGroup数组,存放main线程组中的子线程组
maingroup.enumerate(threadGroups);//将main线程组中的子线程组以复制的形式存放到ThreadGroup数组内
System.out.println("子线程组的名字是; "+threadGroups[0].getName());//输出那个子线程组的名字
System.out.println(threadGroup.getName()+"的父线程组的名字是:"+threadGroup.getParent());
}
}
这个例子说明在实例化一个ThreadGroup的时候,如果不指定归属的线程组,那么该线程组会被自动归属到当前线程对象所属的线程组中。上面的例子中的main线程组的子线程组个数由0变成了1,就是这个原因。
组内线程批量停止
既然是线程组,那么我们可以批量的操作与管理组内的线程。
class MyThread extends Thread{
public MyThread(ThreadGroup threadGroup, String name){
super(threadGroup,name);
}
@Override
public void run() {
System.out.println("线程组:"+Thread.currentThread().getThreadGroup().getName()+"中的 "+Thread.currentThread().getName()+" 开始执行");
while(!isInterrupted()){
//无限死循环
}
System.out.println("线程组:"+Thread.currentThread().getThreadGroup().getName()+"中的 "+Thread.currentThread().getName()+" 结束了");
}
}
public class Main{
public static void main(String[] args){
ThreadGroup my_group = new ThreadGroup("我的线程组");
for(int i = 1;i<=5;i++) {
new MyThread(my_group, "线程" + i).start();//创建新的线程,放到线程组中。
}//启动所有线程
try {
Thread.sleep(3000);
}catch (InterruptedException i){
i.printStackTrace();
}
my_group.interrupt();
}
}
首先创建一个线程组,然后在组中启动五个线程,让它们进入死循环。当我们调用了ThreadGroup中的interrupt()方法时,相当于给线程组中每个线程都调用了interrupt()方法,所以isInterrupted()方法返回false,五个线程批量停止。当然,除了停止之外我们还可以调用ThreadGroup中的其他方法批量管理子线程。这只是个例子罢了。
有关线程组的概念就总结到这里,希望对大家能有所帮助。