Java多線程16:線程組

線程組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。

相關文章
相關標籤/搜索