日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

一、簡介

在之前的多線程系列文章中,我們陸陸續續的介紹了Thread線程類相關的知識和用法,其實在Thread類上還有一層ThreadGroup類,也就是線程組。

今天我們就一起來簡單的聊聊線程組相關的知識和用法。

二、什么是線程組

線程組,簡單來說就是多個線程的集合,它的出現主要是為了更方便的管理線程。

從結構角度看,線程組與線程之間其實是一個父子結構,一個線程組可以擁有幾個線程,同時也可以擁有幾個線程組。整個組織結構像一棵樹一樣,每個線程一定有一個線程組,線程組可能又有一個父線程組,追溯到根節點就是一個系統線程組。

線程組與線程之間的關系,可以用如下圖來描述。

什么是線程組?你學會了嗎?

比如,我們通常創建的mAIn方法,對應的是main線程,它所屬的是main線程組,main線程組的父級是是system系統線程組。

public static void main(String[] args) {
    Thread currentThread = Thread.currentThread();
    ThreadGroup currentThreadGroup = currentThread.getThreadGroup();
    ThreadGroup systemThreadGroup = currentThreadGroup.getParent();
    System.out.println("currentThread:" + currentThread.getName());
    System.out.println("currentThreadGroup:" + currentThreadGroup.getName());
    System.out.println("systemThreadGroup:" + systemThreadGroup.getName());
}

輸出結果如下:

currentThread:main
currentThreadGroup:main
systemThreadGroup:system

其中system線程組就是根節點,再上一層就沒有了,如果調用會拋空指針異常。

線程組最主要的作用是:可以實現批量管理線程或者線程組,有效的對線程或者線程組對象進行檢查、嘗試中斷等操作。

下面我們就一起來看看ThreadGroup的常用方法和使用技巧。

三、線程組用法詳解

3.1、構造方法介紹

ThreadGroup提供了兩個構造方法,內容如下:

方法 描述
ThreadGroup(String name) 根據線程組名稱創建線程組,其父線程組為main線程組
ThreadGroup(ThreadGroup parent, String name) 根據線程組名稱創建線程組,其父線程組為指定的 parent 線程組

其中支持指定父級線程組的方法,在實際的使用中比較常見。

下面,我們演示一下這兩個構造函數的用法:

public static void main(String[] args) {
    ThreadGroup subThreadGroup1 = new ThreadGroup("sub1");
    ThreadGroup subThreadGroup2 = new ThreadGroup(subThreadGroup1, "sub2");
    System.out.println("sub1 parent thread group name:" + subThreadGroup1.getParent().getName());
    System.out.println("sub2 parent thread group name:" + subThreadGroup2.getParent().getName());
}

輸出結果如下:

sub1 parent thread group name:main
sub2 parent thread group name:sub1

3.2、核心方法介紹

ThreadGroup提供了很多有用的方法,下面整理了一些方法的簡要介紹,內容如下:

方法 描述
public final String getName() 返回此線程組的名稱
public final ThreadGroup getParent() 返回此線程組的父級
public final boolean parentOf(ThreadGroup g) 測試此線程組是線程組參數還是其父級線程組之一
public int activeCount() 返回此線程組及其子組中活動線程的數量的估計值,遞歸遍歷該線程組中所有的子組,此方法主要用于調試和監視目的
public int activeGroupCount () 返回此線程組及其子組中活動組的數目的估計值。遞歸遍歷該線程組中的所有子群,此方法主要用于調試和監視目的
public final void checkAccess() 確定當前運行的線程是否具有修改此線程組的權限
public int enumerate(Thread[] list) 將這個線程組復制到它所在的組及其子組中
public final void destroy() 銷毀此線程組及其所有子組,當線程組還要子線程或者子線程組,會拋異常
public boolean isDestroyed() 測試此線程組是否已被銷毀
public final int getMaxPriority() 返回此線程組的最大優先級
public final void setMaxPriority(int pri) 設置組的最大優先級。線程組中具有較高優先級的線程不會受到影響
public final boolean isDaemon() 測試此線程組是否是守護線程組
public final void setDaemon(boolean daemon) 修改此線程組的守護進程狀態
public final void interrupt() 嘗試中斷此線程組中的所有線程
public void list() 將此線程組的信息打印到標準輸出。此方法僅用于調試

下面我們抽取幾個比較常見的方法,進行演示介紹。

3.2.1、activeCount 方法

activeCount()方法用于返回此線程組及其子組中活動線程的數量的估計值,因為線程的數量是動態發生變化的,返回的值只是一個估計值。

我們看一個簡單的例子就知道了。

public class MyThread extends Thread{

    public MyThread(ThreadGroup group, String name) {
        super(group, name);
    }

    @Override
    public void run() {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class MyThreadMainTest {

    public static void main(String[] args) throws Exception {
        ThreadGroup tg = new ThreadGroup("group1");
        MyThread t1 = new MyThread (tg, "t1");
        MyThread t2 = new MyThread (tg, "t2");
        t1.start();
        t2.start();

        System.out.println("線程組的名稱:" +  tg.getName() + ",活動的線程數:" +  tg.activeCount());
        Thread.sleep(1000);
        System.out.println("線程組的名稱:" +  tg.getName() + ",活動的線程數:" +  tg.activeCount());
    }
}

輸出結果如下:

線程組的名稱:group1,活動的線程數:2
線程組的名稱:group1,活動的線程數:0

第一次檢查線程都處于運行狀態,因此活動的線程數為 2;過 1 秒之后,線程運行結束,活動的線程數為 0。

3.2.2、isDaemon 方法

setDaemon()方法用于測試此線程組是否是守護線程組。

需要注意的是:后臺線程組和后臺線程是兩個概念,后臺線程組的特性是最后一個線程執行完或最后一個線程被銷毀時,后臺線程組自動銷毀,線程組只是為了統一管理線程的一個方式,跟后臺線程有區別!

例子如下:

public class MyThread extends Thread{

    public MyThread(ThreadGroup group, String name) {
        super(group, name);
    }

    @Override
    public void run() {
        System.out.println("當前線程:" + Thread.currentThread().getName() + ",是否后臺線程:" +  Thread.currentThread().isDaemon());
        System.out.println("當前線程組:" + Thread.currentThread().getThreadGroup().getName() + ",是否后臺線程組:" +  Thread.currentThread().getThreadGroup().isDaemon());
    }
}

public class MyThreadMainTest4 {

    public static void main(String[] args) throws Exception {
        ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
        new MyThread(mainGroup, "t1").start();

        Thread.sleep(100);

        // 設置守護線程組
        ThreadGroup tg = new ThreadGroup("group1");
        tg.setDaemon(true);
        new MyThread(tg,"t2").start();
    }
}

輸出結果如下:

當前線程:t1,是否后臺線程:false
當前線程組:main,是否后臺線程組:false
當前線程:t2,是否后臺線程:false
當前線程組:group1,是否后臺線程組:true
3.2.3、interrupt 方法

interrupt()方法用于嘗試中斷此線程組中的所有線程。如果正在運行的線程沒有進入阻塞,是無法中斷的。

例子如下:

public class MyThreadA extends Thread{

    public MyThreadA(ThreadGroup group, String name) {
        super(group, name);
    }

    @Override
    public void run() {
        System.out.println("線程:" + Thread.currentThread().getName() + ",開始運行");
        String t;
        for (int i = 0; i < 1000000000; i++) {
            t = i + "";
        }
        System.out.println("線程:" + Thread.currentThread().getName() + ",停止運行");
    }
}
public class MyThreadB extends Thread{

    public MyThreadB(ThreadGroup group, String name) {
        super(group, name);
    }

    @Override
    public void run() {
        System.out.println("線程:" + Thread.currentThread().getName() + ",開始運行");
        while (!Thread.interrupted()){
        }
        System.out.println("線程:" + Thread.currentThread().getName() + ",停止運行");
    }
}
public class MyThreadC extends Thread{

    public MyThreadC(ThreadGroup group, String name) {
        super(group, name);
    }

    @Override
    public void run() {
        System.out.println("線程:" + Thread.currentThread().getName() + ",開始運行");
        try {
            Thread.sleep(1000);
        } catch (Exception e){
//            e.printStackTrace();
        }
        System.out.println("線程:" + Thread.currentThread().getName() + ",停止運行");
    }
}
public class MyThreadMainTest {

    public static void main(String[] args) throws Exception {
        ThreadGroup tg = new ThreadGroup("group1");
        new MyThreadA(tg,"t1").start();
        new MyThreadB(tg,"t2").start();
        new MyThreadC(tg,"t3").start();

        // 嘗試中斷線程組里面的線程
        tg.interrupt();
    }
}

輸出結果如下:

線程:t1,開始運行
線程:t2,開始運行
線程:t2,停止運行
線程:t3,開始運行
線程:t3,停止運行

線程t1只有等它運行結束,通過interrupt()不能中斷程序!

四、小結

本文主要圍繞線程組的一些基本概念以及常用方法,并結合了一些簡單示例進行介紹。

線程組的出現更多的是便于有組織的管理線程,比如 JAVA 的線程池就用到了線程組,更多的線程知識,我們在后續的文章中會進行介紹。

如果有描述不對的地方,歡迎網友留言指出。

五、參考

1、https://www.cnblogs.com/xrq730/p/4856072.html

2、https://cloud.tencent.com/developer/article/1633465

分享到:
標簽:線程
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定