線程組
我們可以把線程歸屬到某個線程組中,線程組可以包含多個線程以及線程組,線程和線程組組成了父子關系,是個樹形結構,如下圖:
使用線程組可以方便管理線程,線程組提供了一些方法方便方便我們管理線程。
創建線程關聯線程組
創建線程的時候,可以給線程指定一個線程組,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
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>:微信公眾號:路人甲Java,專注于java技術分享(帶你玩轉 爬蟲、分布式事務、異步消息服務、任務調度、分庫分表、大數據等),喜歡請關注! */ 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( "活動線程數:" + threadGroup.activeCount()); System.out.println( "活動線程組:" + threadGroup.activeGroupCount()); System.out.println( "線程組名稱:" + threadGroup.getName()); } } |
輸出結果:
threadName:t1
threadName:t2
活動線程數:2
活動線程組:0
線程組名稱:thread-group-1
activeCount()方法可以返回線程組中的所有活動線程數,包含下面的所有子孫節點的線程,由于線程組中的線程是動態變化的,這個值只能是一個估算值。
為線程組指定父線程組
創建線程組的時候,可以給其指定一個父線程組,也可以不指定,如果不指定父線程組,則父線程組為當前線程的線程組,java api有2個常用的構造方法用來創建線程組:
1
2
|
public ThreadGroup(String name) public ThreadGroup(ThreadGroup parent, String name) |
第一個構造方法未指定父線程組,看一下內部的實現:
1
2
3
|
public ThreadGroup(String name) { this (Thread.currentThread().getThreadGroup(), name); } |
系統自動獲取當前線程的線程組作為默認父線程組。
上一段示例代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
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>:微信公眾號:路人甲Java,專注于java技術分享(帶你玩轉 爬蟲、分布式事務、異步消息服務、任務調度、分庫分表、大數據等),喜歡請關注! */ public class Demo2 { public static class R1 implements Runnable { @Override public void run() { Thread thread = Thread.currentThread(); System.out.println( "所屬線程組:" + thread.getThreadGroup().getName() + ",線程名稱:" + 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活動線程數:" + threadGroup1.activeCount()); System.out.println( "threadGroup1活動線程組:" + threadGroup1.activeGroupCount()); System.out.println( "threadGroup1線程組名稱:" + threadGroup1.getName()); System.out.println( "threadGroup1父線程組名稱:" + 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活動線程數:" + threadGroup2.activeCount()); System.out.println( "threadGroup2活動線程組:" + threadGroup2.activeGroupCount()); System.out.println( "threadGroup2線程組名稱:" + threadGroup2.getName()); System.out.println( "threadGroup2父線程組名稱:" + threadGroup2.getParent().getName()); System.out.println( "----------------------" ); System.out.println( "threadGroup1活動線程數:" + threadGroup1.activeCount()); System.out.println( "threadGroup1活動線程組:" + threadGroup1.activeGroupCount()); System.out.println( "----------------------" ); threadGroup1.list(); } } |
輸出結果:
所屬線程組:thread-group-1,線程名稱:t1
所屬線程組:thread-group-1,線程名稱:t2
threadGroup1活動線程數:2
threadGroup1活動線程組:0
threadGroup1線程組名稱:thread-group-1
threadGroup1父線程組名稱:main
----------------------
所屬線程組:thread-group-2,線程名稱:t4
所屬線程組:thread-group-2,線程名稱:t3
threadGroup2活動線程數:2
threadGroup2活動線程組:0
threadGroup2線程組名稱:thread-group-2
threadGroup2父線程組名稱:thread-group-1
----------------------
threadGroup1活動線程數:4
threadGroup1活動線程組: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]
代碼解釋:
1.threadGroup1
未指定父線程組,系統獲取了主線程的線程組作為threadGroup1的父線程組,輸出結果中是:main
2.threadGroup1
為threadGroup2的父線程組
3.threadGroup1
活動線程數為4,包含了threadGroup1線程組中的t1、t2,以及子線程組threadGroup2中的t3、t4
4.線程組的list()方法,將線程組中的所有子孫節點信息輸出到控制臺,用于調試使用
根線程組
獲取根線程組
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package com.itsoku.chat02; /** * <b>description</b>:<br> * <b>time</b>:2019/7/13 17:53 <br> * <b>author</b>:微信公眾號:路人甲Java,專注于java技術分享(帶你玩轉 爬蟲、分布式事務、異步消息服務、任務調度、分庫分表、大數據等),喜歡請關注! */ 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()); } } |
運行上面代碼,輸出:
Thread[main,5,main]
java.lang.ThreadGroup[name=main,maxpri=10]
java.lang.ThreadGroup[name=system,maxpri=10]
null
從上面代碼可以看出:
1.主線程的線程組為main
2.根線程組為system
看一下ThreadGroup的源碼:
1
2
3
4
5
|
private ThreadGroup() { // called from C code this .name = "system" ; this .maxPriority = Thread.MAX_PRIORITY; this .parent = null ; } |
發現ThreadGroup默認構造方法是private的,是由c調用的,創建的正是system線程組。
批量停止線程
調用線程組interrupt(),會將線程組樹下的所有子孫線程中斷標志置為true,可以用來批量中斷線程。
示例代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
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>:微信公眾號:路人甲Java,專注于java技術分享(帶你玩轉 爬蟲、分布式事務、異步消息服務、任務調度、分庫分表、大數據等),喜歡請關注! */ public class Demo4 { public static class R1 implements Runnable { @Override public void run() { Thread thread = Thread.currentThread(); System.out.println( "所屬線程組:" + thread.getThreadGroup().getName() + ",線程名稱:" + 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,線程名稱:t1
所屬線程組:thread-group-1,線程名稱:t2
所屬線程組:thread-group-2,線程名稱:t3
所屬線程組:thread-group-2,線程名稱: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]
停止線程之后,通過list()方法可以看出輸出的信息中不包含已結束的線程了。
總結
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注服務器之家的更多內容!
原文鏈接:https://itsoku.blog.csdn.net/article/details/100036280