Java併發 之 執行緒組 ThreadGroup 介紹

lijiangtao發表於2019-04-02

執行緒組介紹

執行緒組(ThreadGroup)簡單來說就是一個執行緒集合。執行緒組的出現是為了更方便地管理執行緒。

執行緒組是父子結構的,一個執行緒組可以整合其他執行緒組,同時也可以擁有其他子執行緒組。從結構上看,執行緒組是一個樹形結構,每個執行緒都隸屬於一個執行緒組,執行緒組又有父執行緒組,這樣追溯下去,可以追溯到一個根執行緒組——System執行緒組。

Java併發 之 執行緒組 ThreadGroup 介紹

下面介紹一下執行緒組樹的結構:

  1. JVM建立的system執行緒組是用來處理JVM的系統任務的執行緒組,例如物件的銷燬等。
  2. system執行緒組的直接子執行緒組是main執行緒組,這個執行緒組至少包含一個main執行緒,用於執行main方法。
  3. main執行緒組的子執行緒組就是應用程式建立的執行緒組。

你可以在main方法中看到JVM建立的system執行緒組和main執行緒組:

public static void main(String[] args) {
      ThreadGroup mainThreadGroup=Thread.currentThread().getThreadGroup();
      ThreadGroup systenThreadGroup=mainThreadGroup.getParent();
      System.out.println("systenThreadGroup name = "+systenThreadGroup.getName());
      System.out.println("mainThreadGroup name = "+mainThreadGroup.getName());
  }
複製程式碼

console輸出:

systenThreadGroup name = system
mainThreadGroup name = main
複製程式碼

一個執行緒可以訪問其所屬執行緒組的資訊,但不能訪問其所屬執行緒組的父執行緒組或者其他執行緒組的資訊。

執行緒組的構造

java.lang.ThreadGroup提供了兩個建構函式:

Constructor Description
ThreadGroup(String name) 根據執行緒組名稱建立執行緒組,其父執行緒組為main執行緒組
ThreadGroup(ThreadGroup parent, String name) 根據執行緒組名稱建立執行緒組,其父執行緒組為指定的parent執行緒組

下面演示一下這兩個建構函式的用法:

public static void main(String[] args) {
	ThreadGroup subThreadGroup1 = new ThreadGroup("subThreadGroup1");
	ThreadGroup subThreadGroup2 = new ThreadGroup(subThreadGroup1, "subThreadGroup2");
	System.out.println("subThreadGroup1 parent name = " + subThreadGroup1.getParent().getName());
	System.out.println("subThreadGroup2 parent name = " + subThreadGroup2.getParent().getName());
}
複製程式碼

console輸出:

subThreadGroup1 parent name = main
subThreadGroup2 parent name = subThreadGroup1
複製程式碼

ThreadGroup方法介紹

ThreadGroup提供了很多有用的方法,下面提供了這些方法的簡要介紹,以及部分方法的使用示例。

S.N. Method Description
1) void checkAccess() This method determines if the currently running thread has permission to modify the thread group.
2) int activeCount() This method returns an estimate of the number of active threads in the thread group and its subgroups.
3) int activeGroupCount() This method returns an estimate of the number of active groups in the thread group and its subgroups.
4) void destroy() This method destroys the thread group and all of its subgroups.
5) int enumerate(Thread[] list) This method copies into the specified array every active thread in the thread group and its subgroups.
6) int getMaxPriority() This method returns the maximum priority of the thread group.
7) String getName() This method returns the name of the thread group.
8) ThreadGroup getParent() This method returns the parent of the thread group.
9) void interrupt() This method interrupts all threads in the thread group.
10) boolean isDaemon() This method tests if the thread group is a daemon thread group.
11) void setDaemon(boolean daemon) This method changes the daemon status of the thread group.
12) boolean isDestroyed() This method tests if this thread group has been destroyed.
13) void list() This method prints information about the thread group to the standard output.
14) boolean parentOf(ThreadGroup g) This method tests if the thread group is either the thread group argument or one of its ancestor thread groups.
15) void suspend() This method is used to suspend all threads in the thread group.
16) void resume() This method is used to resume all threads in the thread group which was suspended using suspend() method.
17) void setMaxPriority(int pri) This method sets the maximum priority of the group.
18) void stop() This method is used to stop all threads in the thread group.
19) String toString() This method returns a string representation of the Thread group.

檢視執行緒組資訊

下面演示了檢視當前執行緒組的資訊。

public static void list(){
		ThreadGroup tg = new ThreadGroup ("subgroup 1");
		Thread t1 = new Thread (tg, "thread 1");
		Thread t2 = new Thread (tg, "thread 2");
		Thread t3 = new Thread (tg, "thread 3");
		tg = new ThreadGroup ("subgroup 2");
		Thread t4 = new Thread (tg, "my thread");
		tg = Thread.currentThread ().getThreadGroup ();
		int agc = tg.activeGroupCount ();
		System.out.println ("Active thread groups in " + tg.getName () + " thread group: " + agc);
		tg.list ();
}
複製程式碼

輸出如下:

Active thread groups in main thread group: 2
java.lang.ThreadGroup[name=main,maxpri=10]
    Thread[main,5,main]
    java.lang.ThreadGroup[name=subgroup 1,maxpri=10]
    java.lang.ThreadGroup[name=subgroup 2,maxpri=10]
複製程式碼

終止執行緒組中的所有執行緒

一個執行緒應由其他執行緒來強制中斷或停止,而是應該由執行緒自己自行停止。

因此 Thread.currentThread().stop(), Thread.currentThread().suspend(), Thread.currentThread().resume() 都已經被廢棄了。

interrupt() 方法的作用是通知執行緒應該中斷了,具體到底中斷還是繼續執行,由被通知的執行緒處理。

public class ThreadGroupExampleInterrupt {

    public static void main(String[] args) {

        // Start two threads
        MyThread mt = new MyThread();
        mt.setName("A");
        mt.start();
        mt = new MyThread();
        mt.setName("B");
        mt.start();

        // Wait 2 seconds
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // Interrupt all methods in the same thread group as the main thread
        Thread.currentThread().getThreadGroup().interrupt();

    }


    //一個啟動以後進入等待,直到被interrupt的執行緒
    static class MyThread extends Thread {
        public void run() {
            synchronized ("A") {
                System.out.println(getName() + " about to wait.");
                try {
                    "A".wait();
                } catch (InterruptedException e) {
                    System.out.println(getName() + " interrupted.");
                }
                System.out.println(getName() + " terminating.");
            }
        }
    }

}
複製程式碼

執行main方法輸出:

A about to wait.
B about to wait.
A interrupted.
A terminating.
B interrupted.
B terminating.
複製程式碼

總結

本節介紹了執行緒組(ThreadGroup)的概念,及其結構和建構函式,並演示了使用執行緒組方便地管理組內執行緒的幾個方法。

本節是併發系列教程的一節,更多相關教程可以訪問文章後面的連結。

後續會有更多關於併發程式設計的知識點的介紹,並且會結合企業專案進行實戰介紹,歡迎繼續關注。

Links

作者資源

相關資源

相關文章