線程組
可以把線程歸屬到某一個線程組中,線程組中可以有線程對象,也可以有線程組,組中還可以有線程,這樣的組織結構有點類似於樹的形式,如圖所示:
線程組的作用是:可以批量管理線程或線程組對象,有效地對線程或線程組對象進行組織。
線程關聯線程組:1級關聯
所謂1級關聯就是父對象中有子對象,但並不創建孫對象。這種情況在開發中很常見,比如創建一些線程時,為了有效對這些線程進行阻止管理,通常情況下是創建一個線程組,然后再將部分線程歸屬到該組中,以此來對零散的線程對象進行有效的管理。
看一下簡單的1級關聯的例子:
public class MyThread49 implements Runnable { public void run() { try { while (!Thread.currentThread().isInterrupted()) { System.out.println("ThreadName = " + Thread.currentThread().getName()); Thread.sleep(3000); } } catch (InterruptedException e) { e.printStackTrace(); } } }
public static void main(String[] args) { MyThread49 mt0 = new MyThread49(); MyThread49 mt1 = new MyThread49(); ThreadGroup tg = new ThreadGroup("新建線程組1"); Thread t0 = new Thread(tg, mt0); Thread t1 = new Thread(tg, mt1); t0.start(); t1.start(); System.out.println("活動的線程數為:" + tg.activeCount()); System.out.println("線程組的名稱為:" + tg.getName()); }
看一下運行結果:
活動的線程數為:2 ThreadName = Thread-1 ThreadName = Thread-0 線程組的名稱為:新建線程組1 ThreadName = Thread-1 ThreadName = Thread-0 ThreadName = Thread-1 ThreadName = Thread-0 ThreadName = Thread-1 ThreadName = Thread-0
...
控制台上打印出的信息表示線程組中有兩個線程,並且打印出了線程組的名稱。另外,兩個線程無限隔3秒打印,也符合代碼預期
線程關聯線程組:多級關聯
所謂的多級關聯就是父對象中有子對象,子對象中再創建子對象買也就出現了子孫的效果了。但是這種寫法在開發中不太常見,因為線程樹如果涉及得復雜反而不利於線程對象的管理,不過JDK確實提供了多級關聯的線程樹結構。
多級關聯的代碼就不寫了,簡單看一下怎么使用關機關聯,查看下JDK API的ThreadGroup構造方法:
注意一下第二個,假如要使用多級關聯一般就是用第二個構造函數。第一個參數表示新線程組的父線程組,第二個參數表示新線程組的名稱,有了父線程組和新線程組的名稱,自然可以構造出一個新的線程組來了。
當然用第一個構造方法也是可以的,下一部分就會提到。
另外注意一點,線程必須啟動后才能歸到指定線程組中。
線程組自動歸屬特性
自動歸屬的意思就是自動歸到當前線程組中,看一下例子:
public static void main(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 = new ThreadGroup[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, 組中有線程組數量:0 B處線程:main, 所屬線程:main, 組中有線程組數量:1 第一個線程組名稱為:新的組
從結果看,實例化了一個group出來,沒有指定線程組,那么自動歸到當前線程所屬的線程組中,也就是隱式地在一個線程組中添加了一個子線程組。
根線程組
看一下根線程組:
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 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 extends Thread { public MyThread50(ThreadGroup tg, String name) { super(tg, name); } public void run() { System.out.println("ThreadName = " + Thread.currentThread().getName() + "准備開始死循環了"); while (!this.isInterrupted()){} System.out.println("ThreadName = " + Thread.currentThread().getName() + "結束了"); } }
開3個線程:
public static void main(String[] args) throws InterruptedException { 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。