所有執行緒隸屬一個執行緒組(預設或建立時指定)。建立之初即限制在組內,**無法改變到不同組**。每個應用至少有一個執行緒屬於系統執行緒組。若建立多執行緒不指定組,自動歸屬系統組。
執行緒組也必須隸屬其他組,建構子必須指定父組。若未指定,同樣自動成為系統組屬下。因此應用中所有執行緒組最終以系統組為「父」。
字面難尋原因,帶來些混亂。一般認為因「安全」或「保密」理由。據 Arnold 和 Gosling:《執行緒組中的執行緒可修改組內其他執行緒(含分層最深處)。執行緒無法修改自己所在組或下屬組之外的任何執行緒》。但「修改」具體含義難判斷。
//: TestAccess.java
public class TestAccess {
public static void main(String[] args) {
ThreadGroup x = new ThreadGroup("x"),
y = new ThreadGroup(x, "y"),
z = new ThreadGroup(y, "z");
Thread one = new TestThread1(x, "one"),
two = new TestThread2(z, "two");
}
}
class TestThread1 extends Thread {
private int i;
TestThread1(ThreadGroup g, String name) { super(g, name); }
void f() { i++; System.out.println(getName() + " f()"); }
}
class TestThread2 extends TestThread1 {
TestThread2(ThreadGroup g, String name) { super(g, name); start(); }
public void run() {
ThreadGroup g = getThreadGroup().getParent().getParent(); // 向上兩層到 x
g.list();
Thread[] gAll = new Thread[g.activeCount()];
g.enumerate(gAll);
for(int i = 0; i < gAll.length; i++) {
gAll[i].setPriority(Thread.MIN_PRIORITY);
((TestThread1)gAll[i]).f();
}
g.list();
}
} ///:~
java.lang.ThreadGroup[name=x,maxpri=10] Thread[one,5,x] java.lang.ThreadGroup[name=y,maxpri=10] java.lang.ThreadGroup[name=z,maxpri=10] Thread[two,5,z] one f() two f() java.lang.ThreadGroup[name=x,maxpri=10] Thread[one,1,x] java.lang.ThreadGroup[name=y,maxpri=10] java.lang.ThreadGroup[name=z,maxpri=10] Thread[two,1,z]
list() 列印執行緒組/執行緒類名、名稱、最高優先級、所屬組z 的執行緒 two 修改了父組 x 的執行緒 one 優先級並呼叫其方法拋開安全問題,**控制是最實用之處**:單個命令完成整組操作。下例演示優先級限制機制:
maxpri=10,main 執行緒優先級 5g1,嘗試設最高優先級 10 → **失敗,限制為 9**(不可超過父組)g1 到 8,嘗試升回 10 → **失敗**(只能降不能升)g1 到 3(低於預設 6),新建執行緒 C → **仍用預設 6 建立**(組最高優先級不影響預設優先級)g2 隸屬 g1,嘗試提高優先級 → **失敗,限制為 3**(子組不可超過父組)鐵律: 子組最高優先級在任何時候只能 ≤ 父組最高優先級。
sys.suspend() 掛起系統組 → 同時掛起 main 執行緒 → 程式關閉(suspend()/stop() 在 Java 1.2 已棄用)ThreadGroup 繼承 Object 擁有 wait(),可在同步區塊取得物件鎖後調用 wait(毫秒) 暫停任意秒數suspend()/resume() 可中止/啟動整組及子組(同樣棄用)表面看執行緒組讓人摸不著頭腦,**但實務上很少直接使用**。