java高并發(fā)系列-第8天:線程組

線程組

我們可以把線程歸屬到某個(gè)線程組中,線程組可以包含多個(gè)線程以及線程組,線程和線程組組成了父子關(guān)系,是個(gè)樹(shù)形結(jié)構(gòu),如下圖:

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:主機(jī)域名、虛擬主機(jī)、營(yíng)銷(xiāo)軟件、網(wǎng)站建設(shè)、曹妃甸網(wǎng)站維護(hù)、網(wǎng)站推廣。

java高并發(fā)系列 - 第8天:線程組

使用線程組可以方便管理線程,線程組提供了一些方法方便方便我們管理線程。

創(chuàng)建線程關(guān)聯(lián)線程組

創(chuàng)建線程的時(shí)候,可以給線程指定一個(gè)線程組,代碼如下:

package com.itsoku.chat02;

import java.util.concurrent.TimeUnit;

/**
 * <b>description</b>: <br>
 * <b>time</b>:2019/7/13 17:53 <br>
 * <b>author</b>:微信公眾號(hào):路人甲Java,專(zhuān)注于java技術(shù)分享(帶你玩轉(zhuǎn) 爬蟲(chóng)、分布式事務(wù)、異步消息服務(wù)、任務(wù)調(diào)度、分庫(kù)分表、大數(shù)據(jù)等),喜歡請(qǐng)關(guān)注!
 */
public class Demo1 {
    public static class R1 implements Runnable {
        @Override
        public void run() {
            System.out.println("threadName:" + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadGroup threadGroup = new ThreadGroup("thread-group-1");
        Thread t1 = new Thread(threadGroup, new R1(), "t1");
        Thread t2 = new Thread(threadGroup, new R1(), "t2");
        t1.start();
        t2.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("活動(dòng)線程數(shù):" + threadGroup.activeCount());
        System.out.println("活動(dòng)線程組:" + threadGroup.activeGroupCount());
        System.out.println("線程組名稱(chēng):" + threadGroup.getName());
    }
}

輸出結(jié)果:

threadName:t1
threadName:t2
活動(dòng)線程數(shù):2
活動(dòng)線程組:0
線程組名稱(chēng):thread-group-1

activeCount()方法可以返回線程組中的所有活動(dòng)線程數(shù),包含下面的所有子孫節(jié)點(diǎn)的線程,由于線程組中的線程是動(dòng)態(tài)變化的,這個(gè)值只能是一個(gè)估算值。

為線程組指定父線程組

創(chuàng)建線程組的時(shí)候,可以給其指定一個(gè)父線程組,也可以不指定,如果不指定父線程組,則父線程組為當(dāng)前線程的線程組,java api有2個(gè)常用的構(gòu)造方法用來(lái)創(chuàng)建線程組:

public ThreadGroup(String name)
public ThreadGroup(ThreadGroup parent, String name)

第一個(gè)構(gòu)造方法未指定父線程組,看一下內(nèi)部的實(shí)現(xiàn):

public ThreadGroup(String name) {
        this(Thread.currentThread().getThreadGroup(), name);
    }

系統(tǒng)自動(dòng)獲取當(dāng)前線程的線程組作為默認(rèn)父線程組。

上一段示例代碼:

package com.itsoku.chat02;

import java.util.concurrent.TimeUnit;

/**
 * <b>description</b>: <br>
 * <b>time</b>:2019/7/13 17:53 <br>
 * <b>author</b>:微信公眾號(hào):路人甲Java,專(zhuān)注于java技術(shù)分享(帶你玩轉(zhuǎn) 爬蟲(chóng)、分布式事務(wù)、異步消息服務(wù)、任務(wù)調(diào)度、分庫(kù)分表、大數(shù)據(jù)等),喜歡請(qǐng)關(guān)注!
 */
public class Demo2 {
    public static class R1 implements Runnable {
        @Override
        public void run() {
            Thread thread = Thread.currentThread();
            System.out.println("所屬線程組:" + thread.getThreadGroup().getName() + ",線程名稱(chēng):" + thread.getName());
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadGroup threadGroup1 = new ThreadGroup("thread-group-1");
        Thread t1 = new Thread(threadGroup1, new R1(), "t1");
        Thread t2 = new Thread(threadGroup1, new R1(), "t2");
        t1.start();
        t2.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("threadGroup1活動(dòng)線程數(shù):" + threadGroup1.activeCount());
        System.out.println("threadGroup1活動(dòng)線程組:" + threadGroup1.activeGroupCount());
        System.out.println("threadGroup1線程組名稱(chēng):" + threadGroup1.getName());
        System.out.println("threadGroup1父線程組名稱(chēng):" + threadGroup1.getParent().getName());
        System.out.println("----------------------");
        ThreadGroup threadGroup2 = new ThreadGroup(threadGroup1, "thread-group-2");
        Thread t3 = new Thread(threadGroup2, new R1(), "t3");
        Thread t4 = new Thread(threadGroup2, new R1(), "t4");
        t3.start();
        t4.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("threadGroup2活動(dòng)線程數(shù):" + threadGroup2.activeCount());
        System.out.println("threadGroup2活動(dòng)線程組:" + threadGroup2.activeGroupCount());
        System.out.println("threadGroup2線程組名稱(chēng):" + threadGroup2.getName());
        System.out.println("threadGroup2父線程組名稱(chēng):" + threadGroup2.getParent().getName());

        System.out.println("----------------------");
        System.out.println("threadGroup1活動(dòng)線程數(shù):" + threadGroup1.activeCount());
        System.out.println("threadGroup1活動(dòng)線程組:" + threadGroup1.activeGroupCount());

        System.out.println("----------------------");
        threadGroup1.list();
    }
}

輸出結(jié)果:

所屬線程組:thread-group-1,線程名稱(chēng):t1
所屬線程組:thread-group-1,線程名稱(chēng):t2
threadGroup1活動(dòng)線程數(shù):2
threadGroup1活動(dòng)線程組:0
threadGroup1線程組名稱(chēng):thread-group-1
threadGroup1父線程組名稱(chēng):main
----------------------
所屬線程組:thread-group-2,線程名稱(chēng):t4
所屬線程組:thread-group-2,線程名稱(chēng):t3
threadGroup2活動(dòng)線程數(shù):2
threadGroup2活動(dòng)線程組:0
threadGroup2線程組名稱(chēng):thread-group-2
threadGroup2父線程組名稱(chēng):thread-group-1
----------------------
threadGroup1活動(dòng)線程數(shù):4
threadGroup1活動(dòng)線程組:1
----------------------
java.lang.ThreadGroup[name=thread-group-1,maxpri=10]
    Thread[t1,5,thread-group-1]
    Thread[t2,5,thread-group-1]
    java.lang.ThreadGroup[name=thread-group-2,maxpri=10]
        Thread[t3,5,thread-group-2]
        Thread[t4,5,thread-group-2]

代碼解釋?zhuān)?/p>

  1. threadGroup1未指定父線程組,系統(tǒng)獲取了主線程的線程組作為threadGroup1的父線程組,輸出結(jié)果中是:main
  2. threadGroup1為threadGroup2的父線程組
  3. threadGroup1活動(dòng)線程數(shù)為4,包含了threadGroup1線程組中的t1、t2,以及子線程組threadGroup2中的t3、t4
  4. 線程組的list()方法,將線程組中的所有子孫節(jié)點(diǎn)信息輸出到控制臺(tái),用于調(diào)試使用

根線程組

獲取根線程組

package com.itsoku.chat02;

/**
 * <b>description</b>: <br>
 * <b>time</b>:2019/7/13 17:53 <br>
 * <b>author</b>:微信公眾號(hào):路人甲Java,專(zhuān)注于java技術(shù)分享(帶你玩轉(zhuǎn) 爬蟲(chóng)、分布式事務(wù)、異步消息服務(wù)、任務(wù)調(diào)度、分庫(kù)分表、大數(shù)據(jù)等),喜歡請(qǐng)關(guān)注!
 */
public class Demo3 {

    public static void main(String[] args) {
        System.out.println(Thread.currentThread());
        System.out.println(Thread.currentThread().getThreadGroup());
        System.out.println(Thread.currentThread().getThreadGroup().getParent());
        System.out.println(Thread.currentThread().getThreadGroup().getParent().getParent());
    }
}

運(yùn)行上面代碼,輸出:

Thread[main,5,main]
java.lang.ThreadGroup[name=main,maxpri=10]
java.lang.ThreadGroup[name=system,maxpri=10]
null

從上面代碼可以看出:

  1. 主線程的線程組為main
  2. 根線程組為system

看一下ThreadGroup的源碼:

private ThreadGroup() {     // called from C code
        this.name = "system";
        this.maxPriority = Thread.MAX_PRIORITY;
        this.parent = null;
    }

發(fā)現(xiàn)ThreadGroup默認(rèn)構(gòu)造方法是private的,是由c調(diào)用的,創(chuàng)建的正是system線程組。

批量停止線程

調(diào)用線程組interrupt(),會(huì)將線程組樹(shù)下的所有子孫線程中斷標(biāo)志置為true,可以用來(lái)批量中斷線程。

示例代碼:

package com.itsoku.chat02;

import java.util.concurrent.TimeUnit;

/**
 * <b>description</b>: <br>
 * <b>time</b>:2019/7/13 17:53 <br>
 * <b>author</b>:微信公眾號(hào):路人甲Java,專(zhuān)注于java技術(shù)分享(帶你玩轉(zhuǎn) 爬蟲(chóng)、分布式事務(wù)、異步消息服務(wù)、任務(wù)調(diào)度、分庫(kù)分表、大數(shù)據(jù)等),喜歡請(qǐng)關(guān)注!
 */
public class Demo4 {
    public static class R1 implements Runnable {
        @Override
        public void run() {
            Thread thread = Thread.currentThread();
            System.out.println("所屬線程組:" + thread.getThreadGroup().getName() + ",線程名稱(chēng):" + thread.getName());
            while (!thread.isInterrupted()) {
                ;
            }
            System.out.println("線程:" + thread.getName() + "停止了!");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadGroup threadGroup1 = new ThreadGroup("thread-group-1");
        Thread t1 = new Thread(threadGroup1, new R1(), "t1");
        Thread t2 = new Thread(threadGroup1, new R1(), "t2");
        t1.start();
        t2.start();

        ThreadGroup threadGroup2 = new ThreadGroup(threadGroup1, "thread-group-2");
        Thread t3 = new Thread(threadGroup2, new R1(), "t3");
        Thread t4 = new Thread(threadGroup2, new R1(), "t4");
        t3.start();
        t4.start();
        TimeUnit.SECONDS.sleep(1);

        System.out.println("-----------threadGroup1信息-----------");
        threadGroup1.list();

        System.out.println("----------------------");
        System.out.println("停止線程組:" + threadGroup1.getName() + "中的所有子孫線程");
        threadGroup1.interrupt();
        TimeUnit.SECONDS.sleep(2);

        System.out.println("----------threadGroup1停止后,輸出信息------------");
        threadGroup1.list();
    }
}

輸出:

所屬線程組:thread-group-1,線程名稱(chēng):t1
所屬線程組:thread-group-1,線程名稱(chēng):t2
所屬線程組:thread-group-2,線程名稱(chēng):t3
所屬線程組:thread-group-2,線程名稱(chēng):t4
-----------threadGroup1信息-----------
java.lang.ThreadGroup[name=thread-group-1,maxpri=10]
    Thread[t1,5,thread-group-1]
    Thread[t2,5,thread-group-1]
    java.lang.ThreadGroup[name=thread-group-2,maxpri=10]
        Thread[t3,5,thread-group-2]
        Thread[t4,5,thread-group-2]
----------------------
停止線程組:thread-group-1中的所有子孫線程
線程:t4停止了!
線程:t2停止了!
線程:t1停止了!
線程:t3停止了!
----------threadGroup1停止后,輸出信息------------
java.lang.ThreadGroup[name=thread-group-1,maxpri=10]
    java.lang.ThreadGroup[name=thread-group-2,maxpri=10]

停止線程之后,通過(guò)list()方法可以看出輸出的信息中不包含已結(jié)束的線程了。

多說(shuō)幾句,建議大家再創(chuàng)建線程或者線程組的時(shí)候,給他們?nèi)∫粋€(gè)有意義的名字,對(duì)于計(jì)算機(jī)來(lái)說(shuō),可能名字并不重要,但是在系統(tǒng)出問(wèn)題的時(shí)候,你可能會(huì)去查看線程堆棧信息,如果你看到的都是t1、t2、t3,估計(jì)自己也比較崩潰,如果看到的是httpAccpHandler、dubboHandler類(lèi)似的名字,應(yīng)該會(huì)好很多。

java高并發(fā)系列連載中,總計(jì)估計(jì)會(huì)有四五十篇文章,可以關(guān)注公眾號(hào):javacode2018,獲取最新文章。

java高并發(fā)系列 - 第8天:線程組

文章題目:java高并發(fā)系列-第8天:線程組
轉(zhuǎn)載注明:http://bm7419.com/article0/jcseoo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號(hào)商城網(wǎng)站、網(wǎng)站設(shè)計(jì)、品牌網(wǎng)站建設(shè)、響應(yīng)式網(wǎng)站、網(wǎng)站策劃

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

綿陽(yáng)服務(wù)器托管