線程組java
能夠把線程歸屬到某一個線程組中,線程組中能夠有線程對象,也能夠有線程組,組中還能夠有線程,這樣的組織結構有點相似於樹的形式,如圖所示:多線程
線程組的做用是:能夠批量管理線程或線程組對象,有效地對線程或線程組對象進行組織。函數
線程關聯線程組:1級關聯this
所謂1級關聯就是父對象中有子對象,但並不建立孫對象。這種狀況在開發中很常見,好比建立一些線程時,爲了有效對這些線程進行阻止管理,一般狀況下是建立一個線程組,而後再將部分線程歸屬到該組中,以此來對零散的線程對象進行有效的管理。spa
看一下簡單的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秒打印,也符合代碼預期code
線程關聯線程組:多級關聯對象
所謂的多級關聯就是父對象中有子對象,子對象中再建立子對象買也就出現了子孫的效果了。可是這種寫法在開發中不太常見,由於線程樹若是涉及得複雜反而不利於線程對象的管理,不過JDK確實提供了多級關聯的線程樹結構。blog
多級關聯的代碼就不寫了,簡單看一下怎麼使用關機關聯,查看下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)
運行結果能夠得出兩個結論:
一、根線程組就是系統線程組system
二、拋空指針異常是由於系統線程組上已經沒有線程組了,因此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。