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中的其他方法批量管理子线程。这只是个例子罢了。
有关线程组的概念就总结到这里,希望对大家能有所帮助。