首爾國立大學(xué)(韓國)校訓(xùn):“真理是我的光明材泄。”
生活的前方不管有多少荊棘吨岭,我都隨身攜帶著鐮刀拉宗,砥礪前行;烈日高陽辣辫,打一罐雞血旦事,開啟一天的新生活!
前面幾篇聊了很多線程的基礎(chǔ)知識急灭,今天講下線程的家族式管理ThreadGroup族檬,類似中國的宗族制,每個(gè)人都有隸屬的一脈化戳,絕不可能是游離的单料;同樣,jvm管理線程也采用了這種思想点楼,每個(gè)線程也絕不會是游離的扫尖,都有隸屬的ThreadGroup÷永可能大家在工作中沒有注意到它的存在换怖,但在某些場景下還是很有用途的。下面就從線程組的基本概念/管理結(jié)構(gòu)/使用場景簡單聊下:
一 概述線程組
線程組管理線程是一種組織式地管理蟀瞧,類似與公司的組織架構(gòu)管理沉颂,要注意與線程池管理線程進(jìn)行區(qū)分;它是按一定層級結(jié)構(gòu)管理線程或線程組對象悦污,線程和線程組構(gòu)成的結(jié)構(gòu)是樹形铸屉,可以通過遞歸遍歷的方式獲取整個(gè)線程樹。線程組有幾個(gè)重要特性切端,如下:
1/自動(dòng)歸屬彻坛,即線程或線程組具有默認(rèn)機(jī)制,通俗地說,創(chuàng)建一個(gè)線程或線程組昌屉,它必有自己的所屬的線程組钙蒙,每個(gè)線程都不可能是游離的,這可以通過查看new Thread()和new ThreadGroup()的源碼查閱便知间驮。
2/多級關(guān)聯(lián)躬厌,父對象中有子對象,子對象可創(chuàng)建子對象竞帽,子子孫孫無窮盡也烤咧,這是基于jdk提供的線程樹結(jié)構(gòu),但在實(shí)際開發(fā)中抢呆,都是以簡單易讀地方式管理線程煮嫌,所以推薦一級關(guān)聯(lián)。
3/一級關(guān)聯(lián)抱虐,父對象中有子對象昌阿,但不能創(chuàng)建孫對象,即樹形結(jié)構(gòu)只有兩層恳邀,這在實(shí)際工作中大部分場景已經(jīng)夠用懦冰,組織結(jié)構(gòu)越簡單,自然管理也就越簡單谣沸,故在工作中推薦使用刷钢。
demo世界不孤單,請閱:
/**
* @author 阿倫故事
* @Description:描述線程組的基本屬性
* */
@Slf4j
public class GroupBasic {
public static void main(String[] args) {
GroupBasic groupBasic = new GroupBasic();
//auto
groupBasic.auto();
//one level
groupBasic.oneLevel();
//multi level
groupBasic.multiLevel();
}
/**
* 自動(dòng)歸屬
* */
public void auto(){
Thread current = Thread.currentThread();
Thread thread = new Thread(()->{
log.info("---run---");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
log.info("--current thread name:"+current.getName() + "乳附,線程組:"+current.getThreadGroup().getName());
log.info("--new thread name:"+thread.getName() + "内地,線程組:"+thread.getThreadGroup().getName());
}
/**
* 一級關(guān)聯(lián)
* */
public void oneLevel(){
ThreadGroup group = new ThreadGroup("一級線程組");
Thread t1 = new Thread(()->{
log.info("---t1 run---");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(()->{
log.info("---t2 run---");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread one = new Thread(group, t1);
Thread two = new Thread(group, t2);
one.start();
two.start();
log.info("--ThreadGroup name:"+group.getName() + ",存活線程個(gè)數(shù):"+group.activeCount());
}
/**
* 多級關(guān)聯(lián)
* */
public void multiLevel(){
ThreadGroup group = new ThreadGroup("一級線程組");
ThreadGroup group1 = new ThreadGroup(group,"二級線程組A");
ThreadGroup group2 = new ThreadGroup(group,"二級線程組B");
Thread t1 = new Thread(()->{
log.info("---t1 run---");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(()->{
log.info("---t2 run---");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t3 = new Thread(()->{
log.info("---t3 run---");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread one = new Thread(group, t1);
Thread two = new Thread(group1, t2);
Thread three = new Thread(group2, t3);
one.start();
two.start();
three.start();
log.info("--一級線程組 name:"+group.getName() + "赋除,存活線程個(gè)數(shù):"+group.activeCount()
+"阱缓,子線程組個(gè)數(shù):"+group.activeGroupCount());
log.info("--二級線程組A name:"+group1.getName() + ",存活線程個(gè)數(shù):"+group1.activeCount()
+"举农,子線程組個(gè)數(shù):"+group1.activeGroupCount());
log.info("--二級線程組B name:"+group2.getName() + "荆针,存活線程個(gè)數(shù):"+group2.activeCount()
+",子線程組個(gè)數(shù):"+group2.activeGroupCount());
}
}
二 線程批管理
線程組在實(shí)戰(zhàn)中有什么用呢颁糟,主要用對一批線程進(jìn)行管理航背,如中斷(interrupt)/暫停(suspend)/恢復(fù)(resume)/終止(stop)等操作,這里注意下ThreadGroup的destroy方法棱貌,是清除掉這個(gè)線程組及其所有子線程組玖媚,但要注意這里的所有線程組包括子線程組必須是空的,也就是說線程組里的線程都銷亡了键畴,否則會拋出異常最盅。
這里主要講下實(shí)戰(zhàn)中的使用場景:
1/在單個(gè)應(yīng)用中,使用多線程開發(fā)起惕,必然聲明線程池管理線程涡贱,建議根據(jù)業(yè)務(wù)模塊聲明相應(yīng)的線程組來管理,便于針對某一業(yè)務(wù)模塊的線程做統(tǒng)一處理惹想;
2/在任務(wù)調(diào)度模塊中问词,聲明多個(gè)耗時(shí)任務(wù)執(zhí)行數(shù)據(jù)處理,如果定時(shí)任務(wù)長時(shí)間未執(zhí)行完畢嘀粱,可能是由于執(zhí)行過程中出現(xiàn)了異常等激挪,這時(shí)需要把這類任務(wù)終止,就可以利用線程組把一類線程中斷掉锋叨。
demo世界不孤單垄分,請閱:
/**
* @author 阿倫故事
* @Description:描述線程組批處理
* */
@Slf4j
public class GroupBatch {
public static void main(String[] args) throws InterruptedException{
GroupBatch groupBatch = new GroupBatch();
groupBatch.batchTest();
}
/**
* 線程組下的線程任務(wù)執(zhí)行異常,需要全部終止
* */
public void batchTest() throws InterruptedException{
ThreadGroup group = new ThreadGroup("批處理線程組");
for (int i = 0; i <5 ; i++) {
new Thread(group, new SubTask(),"subtask-0"+i).start();
}
Thread.sleep(5000);
log.info("--all SubTask 阻塞娃磺,需終止--");
group.interrupt();//中斷線程組下的所有線程任務(wù)
Thread.sleep(2000);
log.info("--stop the world--");
}
static class SubTask implements Runnable{
@Override
public void run() {
log.info("--subTask thread name:"+ Thread.currentThread().getName() + "薄湿,begin run");
while(!Thread.currentThread().isInterrupted()){ };
log.info("--subTask thread name:"+ Thread.currentThread().getName() + ",end run");
}
}
}
特此聲明:
分享文章有完整的知識架構(gòu)圖偷卧,將從以下幾個(gè)方面系統(tǒng)展開:
1 基礎(chǔ)(Linux/Spring boot/并發(fā))
2 性能調(diào)優(yōu)(jvm/tomcat/mysql)
3 高并發(fā)分布式
4 微服務(wù)體系
如果您覺得文章不錯(cuò)豺瘤,請關(guān)注阿倫故事,您的支持是我堅(jiān)持的莫大動(dòng)力听诸,在此受小弟一拜坐求!
每篇福利: