淺析Java中線程組(ThreadGroup類)

一.概念

Java中使用ThreadGroup類來代表線程組,表示一組線程的集合,可以對(duì)一批線程和線程組進(jìn)行管理??梢园丫€程歸屬到某一個(gè)線程組中,線程組中可以有線程對(duì)象,也可以有線程組,組中還可以有線程,這樣的組織結(jié)構(gòu)有點(diǎn)類似于樹的形式,如圖所示。


線程組

用戶創(chuàng)建的所有線程都屬于指定線程組,如果沒有顯式指定屬于哪個(gè)線程組,那么該線程就屬于默認(rèn)線程組(即main線程組)。默認(rèn)情況下,子線程和父線程處于同一個(gè)線程組。
此外,只有在創(chuàng)建線程時(shí)才能指定其所在的線程組,線程運(yùn)行中途不能改變它所屬的線程組,也就是說線程一旦指定所在的線程組就不能改變。

二.為什么要使用線程組

1.安全

同一個(gè)線程組的線程是可以相互修改對(duì)方的數(shù)據(jù)的。但如果在不同的線程組中,那么就不能“跨線程組”修改數(shù)據(jù),可以從一定程度上保證數(shù)據(jù)安全。

2.批量管理

可以批量管理線程或線程組對(duì)象,有效地對(duì)線程或線程組對(duì)象進(jìn)行組織或控制。

三.線程組使用示例

1.線程關(guān)聯(lián)線程組:一級(jí)關(guān)聯(lián)

所謂一級(jí)關(guān)聯(lián)就是父對(duì)象中有子對(duì)象,但并不創(chuàng)建孫對(duì)象。比如創(chuàng)建一個(gè)線程組,然后將創(chuàng)建的線程歸屬到該組中,從而對(duì)這些線程進(jìn)行有效的管理。代碼示例如下:

public class ThreadGroupTest {
    public static void main(String[] args) {
        ThreadGroup rootThreadGroup = new ThreadGroup("root線程組");
        Thread thread0 = new Thread(rootThreadGroup, new MRunnable(), "線程A");
        Thread thread1 = new Thread(rootThreadGroup, new MRunnable(), "線程B");
        thread0.start();
        thread1.start();
    }
}

class MRunnable implements Runnable {
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("線程名: " + Thread.currentThread().getName() 
+ ", 所在線程組: " + Thread.currentThread().getThreadGroup().getName()) ;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

執(zhí)行結(jié)果如下:

線程名: 線程A, 所在線程組: root線程組
線程名: 線程B, 所在線程組: root線程組

2.線程關(guān)聯(lián)線程組:多級(jí)關(guān)聯(lián)

所謂的多級(jí)關(guān)聯(lián)就是父對(duì)象中有子對(duì)象,子對(duì)象中再創(chuàng)建孫對(duì)象也就出現(xiàn)了子孫的效果了。比如使用下圖第二個(gè)構(gòu)造方法,將子線程組歸屬到某個(gè)線程組,再將創(chuàng)建的線程歸屬到子線程組,這樣就會(huì)有線程樹的效果了。


構(gòu)造方法

代碼示例如下:

public class ThreadGroupTest {
    public static void main(String[] args) {
        ThreadGroup rootThreadGroup = new ThreadGroup("root線程組");
        Thread thread0 = new Thread(rootThreadGroup, new MRunnable(), "線程A");
        Thread thread1 = new Thread(rootThreadGroup, new MRunnable(), "線程B");
        thread0.start();
        thread1.start();
        ThreadGroup threadGroup1 = new ThreadGroup(rootThreadGroup, "子線程組");
        Thread thread2 = new Thread(threadGroup1, new MRunnable(), "線程C");
        Thread thread3 = new Thread(threadGroup1, new MRunnable(), "線程D");
        thread2.start();
        thread3.start();
    }
}

class MRunnable implements Runnable {
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("線程名: " + Thread.currentThread().getName()
                    + ", 所在線程組: " + Thread.currentThread().getThreadGroup().getName()
                    + ", 父線程組: " + Thread.currentThread().getThreadGroup().getParent().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

執(zhí)行結(jié)果如下:

線程名: 線程A, 所在線程組: root線程組, 父線程組: main
線程名: 線程B, 所在線程組: root線程組, 父線程組: main
線程名: 線程C, 所在線程組: 子線程組, 父線程組: root線程組
線程名: 線程D, 所在線程組: 子線程組, 父線程組: root線程組

3.批量管理組內(nèi)線程

使用線程組自然是要對(duì)線程進(jìn)行批量管理,比如可以批量中斷組內(nèi)線程,代碼示例如下:

public class ThreadGroupTest {
    public static void main(String[] args) {
        ThreadGroup rootThreadGroup = new ThreadGroup("root線程組");
        Thread thread0 = new Thread(rootThreadGroup, new MRunnable(), "線程A");
        Thread thread1 = new Thread(rootThreadGroup, new MRunnable(), "線程B");
        thread0.start();
        thread1.start();
        ThreadGroup threadGroup1 = new ThreadGroup(rootThreadGroup, "子線程組");
        Thread thread2 = new Thread(threadGroup1, new MRunnable(), "線程C");
        Thread thread3 = new Thread(threadGroup1, new MRunnable(), "線程D");
        thread2.start();
        thread3.start();
        rootThreadGroup.interrupt();
        System.out.println("批量中斷組內(nèi)線程");
    }
}

class MRunnable implements Runnable {
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("線程名: " + Thread.currentThread().getName()
                    + ", 所在線程組: " + Thread.currentThread().getThreadGroup().getName()
                    + ", 父線程組: " + Thread.currentThread().getThreadGroup().getParent().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
        System.out.println(Thread.currentThread().getName() + "執(zhí)行結(jié)束");
    }
}

執(zhí)行結(jié)果如下:

線程名: 線程A, 所在線程組: root線程組, 父線程組: main
線程名: 線程B, 所在線程組: root線程組, 父線程組: main
線程名: 線程C, 所在線程組: 子線程組, 父線程組: root線程組
線程名: 線程D, 所在線程組: 子線程組, 父線程組: root線程組
批量中斷組內(nèi)線程
線程A執(zhí)行結(jié)束
線程B執(zhí)行結(jié)束
線程C執(zhí)行結(jié)束
線程D執(zhí)行結(jié)束

本文只是對(duì)Java中的ThreadGroup類進(jìn)行了簡(jiǎn)單的介紹和使用示范,更多線程組的操作可以查看JDK API。
參考:
Java多線程16:線程組
Java線程組(ThreadGroup)使用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容