1. 程式人生 > >ThreadGroup執行緒組使用

ThreadGroup執行緒組使用

本文來源於:http://cunzhangok.iteye.com/blog/1633761

ThreadGroup執行緒組表示一個執行緒的集合。此外,執行緒組也可以包含其他執行緒組。 
執行緒組構成一棵樹,在樹中,除了初始執行緒組外,每個執行緒組都有一個父執行緒組。 
允許執行緒訪問有關自己的執行緒組的資訊,但是不允許它訪問有關其執行緒組的父執行緒組或其他任何執行緒組的資訊。 
構造方法 
public ThreadGroup(String name) 
    構造一個新執行緒組。新執行緒組的父執行緒組是目前正在執行執行緒的執行緒組。 
    不使用任何引數呼叫父執行緒組的 checkAccess 方法;這可能導致一個安全性異常。 


    引數: 
        name - 新執行緒組的名稱。 
    丟擲: 
        SecurityException - 如果當前執行緒不能在指定的執行緒組中建立執行緒。 
public ThreadGroup(ThreadGroup parent,String name) 
    建立一個新執行緒組。新執行緒組的父執行緒組是指定的執行緒組。 
    不使用任何引數呼叫父執行緒組的 checkAccess 方法;這可能導致一個安全性異常。 
    引數: 
        parent - 父執行緒組。 
        name - 新執行緒組的名稱。 
    丟擲: 
        NullPointerException - 如果執行緒組引數為 null。 

        SecurityException - 如果當前執行緒不能在指定的執行緒組中建立執行緒。 
  在Java中每個執行緒都屬於某個執行緒組(ThreadGroup)。 
例如,如果在main()中產生一個執行緒,則這個執行緒屬於main執行緒組(其名字為"main")管理的一員,您可以使用下面的指令來獲得目前執行緒所屬的執行緒組名稱: 
Thread.currentThread().getThreadGroup().getName(); 
  每一個執行緒產生時,都會被歸入某個執行緒組,視執行緒是在哪個執行緒組中產生而定。如果沒有指定,則歸入產生該子執行緒的執行緒的執行緒組中。 
您也可以自行指定執行緒組,執行緒一旦歸入某個組,就無法更換組。 

java.lang.ThreadGroup類正如其名,可以統一管理整個執行緒組中的執行緒,您可以使用以下方式來產生執行緒組,而且一併指定其執行緒組: 
ThreadGroup threadGroup1 = new ThreadGroup("group1"); 
ThreadGroup threadGroup2 = new ThreadGroup("group2"); 
Thread thread1 =new Thread(threadGroup1, "group1's member"); 
Thread thread2 =new Thread(threadGroup2, "group2's member"); 
ThreadGroup中的某些方法,可以對所有的執行緒產生作用,例如interrupt()方法可以interrupt執行緒組中所有的執行緒, 
setMaxPriority()方法可以設定執行緒組中執行緒所能擁有的最高優先權(本來就擁有更高優先權的執行緒不受影響)。 
如果您想要一次獲得執行緒組中所有的執行緒來進行某種操作,可以使用enumerate()方法,例如: 
Thread[] threads = new Thread[threadGroup1.activeCount()]; 
threadGroup1.enumerate(threads); 
activeCount()方法獲得執行緒組中正在執行的執行緒數量,enumerate()方法要傳入一個Thread陣列, 
它將執行緒物件設定到每個陣列欄位中,然後就可以通過陣列索引來操作這些執行緒。 
ThreadGroup中有一個uncaughtException()方法。當執行緒組中某個執行緒發生Unchecked exception異常時, 
由執行環境呼叫此方法進行相關處理,如果有必要,您可以重新定義此方法,直接使用範例15.9來示範如何實現。
範例1 
ThreadGroupDemo.java檔案 
    package onlyfun.caterpillar; 
    import java.io.*; 
    public class ThreadGroupDemo { 
    public static void main(String[] args) { 
    ThreadGroup threadGroup1 = 
    // 這是匿名類寫法 
    new ThreadGroup("group1") { 
    // 繼承ThreadGroup並重新定義以下方法 
    // 線上程成員丟擲unchecked exception 
    // 會執行此方法 
    public void uncaughtException(Thread t, Throwable e) { 
    System.out.println(t.getName() + ": " 
    + e.getMessage()); 
    } 
    }; 
    // 這是匿名類寫法 
    Thread thread1 = 
    // 這個執行緒是threadGroup1的一員 
    new Thread(threadGroup1, 
    new Runnable() { 
    public void run() { 
    // 丟擲unchecked異常 
    throw new RuntimeException("測試異常"); 
    } 
    }); 

            thread1.start(); 
    } 
    } 
  在uncaughtException()方法的引數中,第一個引數可以獲得發生異常的執行緒例項,而第二個引數可以獲得異常物件, 
範例中顯示了執行緒的名稱及異常資訊,結果如下所示: 
Thread-0: 測試異常 
在J2SE 5.0之前,如果要統一處理某些執行緒的Unchecked Exception,可以使用ThreadGroup來管理。 
在繼承ThreadGroup之後重新定義其uncaughtException()方法,就如範例1所示。在J2SE 5.0之後,就不用這麼麻煩, 
可以讓異常處理類使用Thread.UncaughtExceptionHandler介面,並實現其 uncaughtException()方法, 
例如可以改寫範例1,首先定義一個類讓其實現 Thread.UncaughtExceptionHandler介面。 
範例2 
ThreadExceptionHandler.java檔案 
package onlyfun.caterpillar; 
public class ThreadExceptionHandler 
implements Thread.UncaughtExceptionHandler { 
public void uncaughtException(Thread t, Throwable e) { 
System.out.println(t.getName() + ": " 
+ e.getMessage()); 


接著範例1主流程可以改寫為範例3。 
範例3 ThreadGroupDemo2.java 
    package onlyfun.caterpillar; 
    import java.io.*; 
    public class ThreadGroupDemo2 { 
    public static void main(String[] args) { 
    // 建立異常處理者 
    ThreadExceptionHandler handler = 
    new ThreadExceptionHandler(); 
    ThreadGroup threadGroup1 = new ThreadGroup("group1"); 
    // 這是匿名類寫法 
    Thread thread1 = 
    // 這個執行緒是threadGroup1的一員 
    new Thread(threadGroup1, 
    new Runnable() { 
    public void run() { 
    // 丟擲unchecked異常 
    throw new RuntimeException("測試異常"); 
    } 
    }); 
    // 設定異常處理者 
    thread1.setUncaughtExceptionHandler(handler); 
    thread1.start(); 
    } 
    } 
需要注意的函式: 
public final void checkAccess() 
    確定當前執行的執行緒是否有權修改此執行緒組。 
    如果有安全管理器,則用此執行緒組作為其引數呼叫 checkAccess 方法。結果可能是丟擲一個 SecurityException。 
    丟擲: 
        SecurityException - 如果不允許當前執行緒訪問此執行緒組。 
注意:它返回的居然是void,而不是boolean.其實如果當前執行的執行緒沒有權修改此執行緒組,則丟擲一個 SecurityException。 
否則不丟擲。 
public int enumerate(Thread[] list) 
    把此執行緒組及其子組中的所有活動執行緒複製到指定陣列中。 
    首先,不使用任何引數呼叫此執行緒組的 checkAccess 方法;這可能導致一個安全性異常。 
    應用程式可以使用 activeCount 方法獲取陣列大小的估計數,但是,如果陣列太小而無法保持所有執行緒,則忽略額外的執行緒。如果獲得此執行緒組及其子組中的所有活動執行緒非常重要,則呼叫方應該驗證返回的 int 值是否嚴格小於 list 的長度。 
    由於使用此方法所固有的競爭條件,建議只將此方法用於資訊目的。 
    引數: 
        list - 放置執行緒列表的陣列。 
    返回: 
        放入陣列中的執行緒數。 
    丟擲: 
        SecurityException - 如果不允許當前執行緒列舉此執行緒組。 
注意:它的目的是把子組中的所有活動執行緒複製到指定陣列list中。還有一些enumerate的函式,具體參考文件。 
public final void interrupt() 
    中斷此執行緒組中的所有執行緒。 
    首先,不使用任何引數呼叫此執行緒組的 checkAccess 方法;這可能導致一個安全性異常。 
    然後,此方法將對此執行緒組及其所有子組中的所有執行緒呼叫 interrupt 方法。 
    丟擲: 
        SecurityException - 如果不允許當前執行緒訪問此執行緒組或執行緒組中的任何執行緒