1. 程式人生 > 實用技巧 >ThreadGroup API介紹

ThreadGroup API介紹

ThreadGroup API介紹

TreadGroup其實是在1.5之前用的比較多,在沒有執行緒池API前都使用TreadGroupApi來管理執行緒池。雖然現在有執行緒池API來供大家使用,但是如果在平時開發中只想啟用三五個執行緒,那麼可以選擇使用TreadGroup來管理執行緒。

我們找到ThreadGroup來看一下:

執行緒組表示一組執行緒。此外,執行緒組還可以包括其他執行緒組。執行緒組形成一個樹,其中除了初始執行緒組外,每個執行緒組都有一個父執行緒組。

允許執行緒訪問關於其自己執行緒組的資訊,但不允許訪問關於其執行緒組的父執行緒組或任何其他執行緒組的資訊。

那麼,允許執行緒訪問關於其自己執行緒組的資訊的資訊都是什麼呢?我們接下來看一下:

首先建立一個threadgroup

public class ThreadGroupCreate {
    public static void main(String[] args) {
        // 1. use the name
        ThreadGroup tg1 = new ThreadGroup("TG1");
        Thread t1 = new Thread(tg1, () -> {
            while (true) {
                try {
                    Thread.sleep(10_000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "T1");
        t1.start();
        System.out.println("t1's thread group name = " + t1.getThreadGroup().getName());// TG1
        //todo  2. use the parent and group name
    }
}

執行效果如下:

列印一下當前threadgroup的名字和他父級的名字:

ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
System.out.println(threadGroup.getName());
System.out.println(threadGroup.getParent());

執行效果如下:

可以看到他的執行緒組是TG1,他的夫級執行緒組是main,並且main執行緒的優先順序很高是10。

接下來我們給建立另一個執行緒組,他的夫級執行緒組TG1:

//2. use the parent and group name
ThreadGroup tg2 = new ThreadGroup(tg1, "TG2");
System.out.println("tg2's name = " + tg2.getName());
System.out.println("tg2's parent name = " + tg2.getParent().getName());

執行效果如下:

執行緒組兩種建立方式就ok了,我們再來驗證一下:允許執行緒訪問關於其自己執行緒組的資訊,但不允許訪問關於其執行緒組的父執行緒組或任何其他執行緒組的資訊

//TG2 訪問TG1
ThreadGroup tg2 = new ThreadGroup(tg1, "TG2");
Thread t2 = new Thread(tg2,()->{
    System.out.println("tg2's parent threadgroup is"+tg2.getName());
});
t2.start();

// TG3與TG1為同一個父ThreadGroup-main
// 測試TG3能否訪問TG1的一些資訊
ThreadGroup tg3 = new ThreadGroup("TG3");
Thread t3 = new Thread(tg3, () -> {
    System.out.println(">>>>" + t1.getName());// TG1
    Thread[] threads = new Thread[tg1.activeCount()];
    tg1.enumerate(threads);
    Stream.of(threads).forEach(System.out::println);// Thread[T1,5,TG1]
}, "T3");
t3.start();

執行效果如下:

可以看到其實是可以訪問的,可能是官方文件有問題,也有可能是我翻譯的有問題。。。

接下來學習幾個ThreadGroup的常用方法:

activeCount()

返回此執行緒組及其子組中活動執行緒的評估數量。這裡注意是評估數量,因為可能獲取的時候,某個執行緒消亡了或者正在被新增。

public class ThreadGroupAPI {
    public static void main(String[] args) {
        ThreadGroup tg1 = new ThreadGroup("TG1");
        Thread t1 = new Thread(tg1, () -> {
            while (true) {
                try {
                    Thread.sleep(1_000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;
                }
            }
        }, "T1");
        /*tg1.setDaemon(true);*/
        t1.start();

        ThreadGroup tg2 = new ThreadGroup(tg1, "TG2");
        Thread t2 = new Thread(tg2, () -> {
            while (true) {
                try {
                    Thread.sleep(1_000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;
                }
            }
        }, "T2");
        t2.start();

        System.out.println("tg1 active count is " + tg1.activeCount());
    }
}

執行效果如下:

activeGroupCount()

返回此執行緒組及其子組中活動組的評估數量。

System.out.println(tg1.activeGroupCount());

執行效果如下:

checkAccess()

確定當前執行的執行緒是否具有修改此執行緒組的許可權。

程式碼如下:

tg1.checkAccess();

執行效果如下:

沒丟擲異常代表有許可權修改執行緒組。

destroy()

銷燬這個執行緒組及其所有子組。destroy前需要確定執行緒組裡沒有活躍的執行緒。如果執行緒組不為空或執行緒組已被銷燬將丟擲IllegalThreadStateException

程式碼如下:

tg1.destroy();

執行效果如下:

因為我們執行緒裡有while,所以是活躍的執行緒,這裡就丟擲異常了。

enumerate(Thread[] list)

將此執行緒組及其子組中的每個活動執行緒複製到指定的陣列中。

程式碼如下:

Thread[] ts1 = new Thread[tg1.activeCount()];
tg1.enumerate(ts1);
System.out.println(Arrays.toString(ts1));

執行效果如下:

enumerate(Thread[] list, boolean recurse)

將此執行緒組中的每個活動執行緒複製到指定陣列中。

程式碼如下:

Thread[] ts2 = new Thread[tg1.activeCount()];
tg1.enumerate(ts2, false);
System.out.println(Arrays.toString(ts2));

執行效果如下:

如果為真,則遞迴列舉此執行緒組的所有子組。那麼我們使用false試試:

ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup();
Thread[] ts3 = new Thread[mainThreadGroup.activeCount()];
mainThreadGroup.enumerate(ts3, false);
System.out.println(Arrays.toString(ts3));

執行效果如下:

interrupt()

中斷此執行緒組中的所有執行緒。

程式碼如下:

tg1.interrupt();

執行效果如下:

setDaemon(boolean daemon)

守護程序——如果為真,則將此執行緒組標記為守護執行緒組;否則,將此執行緒組標記為normal。

 ThreadGroup tg1 = new ThreadGroup("TG1");
    Thread t1 = new Thread(tg1, () -> {
        try {
            Thread.sleep(1_000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }, "T1");
    tg1.setDaemon(true);
    t1.start();
    Thread.sleep(2_000);
    System.out.println(tg1.isDestroyed());

執行效果如下:

註釋tg1.setDaemon(true);試一下:

手動銷燬一下:

ThreadGroup tg1 = new ThreadGroup("TG1");
Thread t1 = new Thread(tg1, () -> {
    try {
        Thread.sleep(1_000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}, "T1");
//tg1.setDaemon(true);
t1.start();
Thread.sleep(2_000);
System.out.println(tg1.isDestroyed());
tg1.destroy();
System.out.println(tg1.isDestroyed());

執行效果如下:

這篇隨筆是我週六沒吃早飯沒吃午飯弄到下午4點38才弄完的,內容雖然你不多但是改來改去,時間也就慢慢過去了,中間多少次想休息一會吃個飯再繼續弄,但是還是想弄完了再好好吃飯,也許這樣下去永遠都胖不起來吧。。。哎精神糧食充實啊~