1. 程式人生 > >執行緒——執行緒實現方式和執行緒屬性

執行緒——執行緒實現方式和執行緒屬性

程序和執行緒

程序是計算機系統中能獨立執行並作為資源分配的基本單位,它是由PCB(程序控制塊),資料段和程式碼段組成,是一個能獨立執行的基本單位.程序的建立,排程,分派都需要較大的時間和空間開銷,在作業系統中引入執行緒,以執行緒作為排程和分派的基本單位,以此來改進多處理機系統的效能

執行緒是作業系統能夠進行運算排程的最小單位,同一個程序中的多條執行緒共享該程序中的全部系統資源

程序與執行緒的區別:

  1. 程序每次排程時,都需要進行上下文切換將斷點的資訊儲存在PCB中,開銷較大.執行緒排程時,只需要儲存和設定少量的暫存器內容,切換代價比較小
  2. 程序作為系統資源分配的基本單位,擁有一定的資源,包括用於存放程式,資料的磁碟和記憶體地址空間,以及在它執行時所需要的I/O裝置,已開啟的訊號量等.而執行緒只擁有一點必不可少的,能保證獨立執行的資源(如控制執行緒執行的TCB,用於指示被執行指令序列的程式計數器,儲存區域性變數,少數狀態引數和返回地址等的一組暫存器和堆疊),允許多個執行緒共享該程序中的記憶體地址空間和資源

java中實現執行緒的兩種方式

java中允許程式併發地執行多個執行緒,併發是指同一時間間隔中有兩個或多個事件同時發生,並行是指同一時刻有兩個或多個事件同時執行.

1. 繼承Thread類並重寫run()方法

Thread表示執行緒類,run方法中是我們啟動執行緒時要做的事,應該使用start()方法啟動執行緒,直接呼叫run方法相當於普通的方法呼叫,下面我們通過繼承Thread類的方式定義了一個執行緒類用來輸出0到9,接著在main方法中建立兩個執行緒類的例項並啟動執行緒,可以看出執行緒的執行情況是隨機的.執行緒的排程細節取決於作業系統,搶佔式的執行緒排程給每個執行緒一個時間片的時間執行該執行緒,當該時間片完時,系統會儲存當前執行緒的狀態,然後終止當前執行緒的執行,執行另一個執行緒,當下一個時間片完時,又會終止當前執行執行緒,依次類推.直到所有執行緒終止.

 1 public class FirstThread extends Thread{
 2     @Override
 3     public void run() {
 4         for(int i = 0;i<10;i++) {
 5             System.out.println(Thread.currentThread().getName()+"列印"+i);
 6         }
 7     }
 8 }
 9 public class FirstDemo {
10     public static void main(String[] args) {
11         Thread thread = new FirstThread();
12         Thread thread2 = new FirstThread();
13         thread.start();
14         thread2.start();
15     }    
16 }

2.實現Runnable介面

Thread類有一個引數為Runnable物件的建構函式,它可以使用給定的Runnable物件建立一個執行緒.

 1 public class FirstThread implements Runnable{
 2     @Override
 3     public void run() {
 4         for(int i = 0;i<10;i++) {
 5             System.out.println(Thread.currentThread().getName()+"列印"+i);
 6         }
 7     }
 8 }
 9 public class FirstDemo {
10     public static void main(String[] args) {
11         Thread thread = new Thread(new FirstThread());
12         Thread thread2 = new Thread(new FirstThread());
13         thread.start();
14         thread2.start();
15     }    
16 }

執行緒屬性

執行緒名(預設Thread-執行緒初始化時的序號)

 1 private String name;
 2 
 3 // 設定執行緒的名字
 4 public final synchronized void setName(String name) {
 5         checkAccess();      // 檢查是否允許更改執行緒的引數
 6 
 7         if (name == null) {
 8             throw new NullPointerException("name cannot be null");
 9         }
10 
11         this.name = name;
12         if (threadStatus != 0) {      // 判斷執行緒的狀態
13             setNativeName(name);
14         }
15 }   
16 
17 // 獲取執行緒的名字
18 public final String getName() {
19        return name;
20 }

執行緒的優先順序(預設是父執行緒的優先順序)

 1 private int priority;
 2 
 3 public final static int MIN_PRIORITY = 1;  // 執行緒的最小優先順序
 4 
 5 public final static int NORM_PRIORITY = 5; // 執行緒的預設優先順序
 6 
 7 public final static int MAX_PRIORITY = 10; // 執行緒的最大優先順序
 8 
 9 // 設定執行緒的優先順序
10 public final void setPriority(int newPriority) {
11      ThreadGroup g;
12      checkAccess();      // 安全檢查
13 
14      // 檢查設定的優先順序是否大於最大優先順序或最小優先順序,如果是丟擲引數不合法異常 
15      if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
16          throw new IllegalArgumentException();
17      }
18 
19      // 獲取當前的執行緒組
20      if((g = getThreadGroup()) != null) {
21         // 如果當前設定的優先順序大於它所線上程組的最大優先順序
22         if (newPriority > g.getMaxPriority()) {
23             // 設定當前執行緒的優先順序為當前執行緒組的最大優先順序
24             newPriority = g.getMaxPriority();
25         }
26         // 呼叫本地方法setPriority0設定執行緒優先順序
27         setPriority0(priority = newPriority);
28     }
29 }
30 
31 // 獲取當前執行緒的優先順序
32 public final int getPriority() {
33     return priority;
34 }
35     

執行緒是否是守護執行緒(預設是父執行緒的值)

守護執行緒是為其他執行緒提供服務的執行緒,當一個程式只剩下守護執行緒了,java虛擬機器就會退出程式,也就是說守護執行緒是依託使用者執行緒而存在的,使用者執行緒的終止將會導致守護執行緒終止,不管當前處於什麼狀態,在使用守護執行緒時,應該避免守護執行緒去訪問固有的資源,如檔案,資料庫等.它會在任何一個操作的中間發生中斷.

 1 private boolean daemon;
 2 
 3 // 設定該執行緒是否是守護執行緒
 4 public final void setDaemon(boolean on) {
 5     // 安全檢查  
 6     checkAccess();
 7     
 8     // 如果執行緒處於活動狀態,丟擲表示沒有線上程適當狀態操作進行的異常
 9     if (isAlive()) {
10         throw new IllegalThreadStateException();
11     }
12     // 設定執行緒是否為守護執行緒
13     daemon = on;
14 }
15 // 判斷當前執行緒是否處於活動狀態
16 public final native boolean isAlive();
17 
18 // 判斷當前執行緒是否是 守護執行緒
19 public final boolean isDaemon() {
20     return daemon;
21 }

執行緒的狀態

執行緒的狀態使用一個內部靜態列舉類表示

 1 public enum State {
 2 
 3     NEW,      // 新建狀態
 4 
 5     RUNNABLE,      // 可執行狀態
 6 
 7     BLOCKED,        // 阻塞狀態
 8 
 9     WAITING,     // 等待狀態
10 
11     TIMED_WAITING,  // 等待一段時間的狀態
12 
13     TERMINATED;  // 終止狀態
14 }
15    
16 // 獲取當前執行緒的狀態
17 public State getState() {
18         // get current thread state
19         return sun.misc.VM.toThreadState(threadStatus);
20 }

執行緒的未捕獲異常處理器

執行緒的run方法沒有丟擲任何的受查異常,如果在執行時丟擲異常,然而並未捕獲處理該異常,該執行緒即將終止,此時就會將該執行緒和異常作為引數呼叫未捕獲異常處理器的方法,未捕獲異常處理器是一個實現UncaughtExceptionHandler介面的類,UncaughtException是Thread的一個靜態內部類,它的內部只有一個方法 void uncaughtException(Thread t, Throwable e); 該方法將會線上程因未捕獲的異常而終止時呼叫.ThreadGroup類實現了該介面.Thread類有兩個UncaughtExceptionHandler介面的變數,一個是預設的處理器(用static修飾),供所有的執行緒使用,另一個只供當前執行緒使用.預設情況下這兩個變數都為null,執行緒使用的未捕獲異常處理器是該執行緒組的處理器.

 1 // 供當前執行緒使用
 2 private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
 3 
 4 // 獲取當前執行緒的未捕獲異常處理器
 5 public UncaughtExceptionHandler getUncaughtExceptionHandler() {
 6     // 如果當前執行緒無未捕獲異常處理器,則返回該執行緒所屬執行緒組的處理器
 7     return uncaughtExceptionHandler != null ?
 8         uncaughtExceptionHandler : group;
 9 }
10 // 設定當前執行緒的未捕獲異常處理器
11 public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
12     checkAccess();
13     uncaughtExceptionHandler = eh;
14 }
15 
16 // 供所有執行緒使用
17 private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
18 
19 // 獲取預設的未捕獲異常處理器
20 public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
21     return defaultUncaughtExceptionHandler;
22 }
23 // 設定預設的未捕獲異常處理器
24 public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
25     
26     // 獲取系統安全管理器
27     SecurityManager sm = System.getSecurityManager();
28     if (sm != null) {
29         // 檢查是否允許執行給定許可權的請求,如果不允許,丟擲SecurityException異常
30         sm.checkPermission(
31 
32 // 建立一個線上程由於未捕獲的異常而突然終止時,設定將要使用的預設處理程式的執行時許可權物件
33             new RuntimePermission("setDefaultUncaughtExceptionHandler")
34                 );
35     }
36     // 設定預設的未捕獲異常處理器  
37     defaultUncaughtExceptionHandler = eh;
38 }
 1 // ThreadGroup 實現Thread.Uncaughtexception介面的原始碼解析
 2 public void uncaughtException(Thread t, Throwable e) {
 3     // 如果該執行緒組有父執行緒組,則使用父執行緒組的處理器
 4     if (parent != null) {
 5         parent.uncaughtException(t, e);
 6     } else {
 7         
 8         // 獲取預設的未捕獲異常處理器
 9         Thread.UncaughtExceptionHandler ueh =
10             Thread.getDefaultUncaughtExceptionHandler();
11         
12         // 如果有預設的異常處理器就使用它
13         if (ueh != null) {
14             ueh.uncaughtException(t, e);
15 
16         } 
17         // 否則判斷引起執行緒終止的異常是否是ThreadDeath的子類,如果是,什麼也不做,負責將執行緒名和堆疊資訊輸出到標準錯誤流中,ThreadDeath是
18         else if (!(e instanceof ThreadDeath)) {
19             System.err.print("Exception in thread \""
20                              + t.getName() + "\" ");
21             e.printStackTrace(System.err);
22         }
23     }
24 }        

執行緒組ThreadGroup

執行緒組是一個統一管理執行緒的集合,除了初始執行緒組,每個執行緒組有一個父執行緒組,執行緒組也可以包含其他執行緒組,允許執行緒訪問有關自己的執行緒組的資訊,但是不允許它訪問有關其執行緒組的父執行緒組或其他任何執行緒組的資訊.預設情況下,建立的執行緒組都屬於main執行緒組.執行緒組有兩個構造方法

執行緒組屬性

 1     private final ThreadGroup parent; // 父執行緒組,一旦指定不可修改
 2     String name; // 執行緒組名
 3     int maxPriority; // 執行緒組的最大優先順序
 4     boolean destroyed; // 執行緒組是否被銷燬
 5     boolean daemon; // 執行緒組是否是守護執行緒組
 6     boolean vmAllowSuspension; // 虛擬機器自動掛起
 7 
 8     int nUnstartedThreads = 0; // 執行緒組中未啟動執行緒的數量
 9     int nthreads; // 此執行緒組包含的執行緒數
10     Thread[] threads[]; // 該執行緒組中包含的執行緒
11 
12     int ngroups; // 子執行緒組計數器
13     ThreadGroup[] groups; // 該執行緒組中包含的執行緒組    
 1 建構函式呼叫順序從上到下
 2 
 3 //使用指定的執行緒組名構造執行緒組
 4 public ThreadGroup(String name) {
 5     // 獲取當前執行緒組的父執行緒組
 6     this(Thread.currentThread().getThreadGroup(), name);
 7 }
 8 
 9 //建立一個父執行緒組時指定執行緒,並且名字為name的執行緒組
10 public ThreadGroup(ThreadGroup parent, String name) {
11     // 檢查父執行緒組
12     this(checkParentAccess(parent), parent, name);
13 }
14 
15 
16 //檢查執行緒組的安全
17 private static Void checkParentAccess(ThreadGroup parent) {
18      parent.checkAccess();
19      return null;
20 }
21 //安全檢查
22 public final void checkAccess() {
23      SecurityManager security = System.getSecurityManager();
24      if (security != null) {
25          security.checkAccess(this);
26      }
27 }
28 
29 private ThreadGroup(Void unused, ThreadGroup parent, String name) {
30     // 設定執行緒組名
31     this.name = name;
32     // 最大優先順序是父執行緒組的最大優先順序    
33     this.maxPriority = parent.maxPriority;
34     // 是否是守護執行緒組合父執行緒組保持一致
35     this.daemon = parent.daemon;
36     // 虛擬機器引數
37     this.vmAllowSuspension = parent.vmAllowSuspension;
38     this.parent = parent;
39     parent.add(this);
40 }
41 // 新增指定的執行緒組
42 private final void add(ThreadGroup g) {
43     synchronized (this) {
44         // 如果執行緒組已經被銷燬,丟擲異常
45         if (destroyed) {
46             throw new IllegalThreadStateException();
47         }
48         // 判斷此執行緒組子執行緒組陣列是否為空或已滿
49         // 如果為空,建立子執行緒陣列,初始容量為4,將指定執行緒組加入該陣列,計數器加一;
50         // 如果子執行緒陣列已滿,陣列容量擴容兩倍,將指定執行緒組存入陣列,計數器加一
51         // 如果子執行緒陣列未滿,將指定執行緒組加入該陣列,計數器加一
52         if (groups == null) {
53             groups = new ThreadGroup[4];
54         } else if (ngroups == groups.length) {
55             groups = Arrays.copyOf(groups, ngroups * 2);
56         }
57         groups[ngroups] = g;
58         ngroups++;
59     }
60 }

其他方法

  1         // 移除指定的執行緒組
  2     private void remove(ThreadGroup g) {
  3         synchronized (this) {
  4             // 判斷該執行緒組是否死亡
  5             if (destroyed) {
  6                 return;
  7             }
  8             // 迴圈遍歷子執行緒組陣列,找到要刪除的執行緒組,如果找到,子執行緒組計數器減一
  9             // 將處於該執行緒組元素後的元素向前移動,將最後一個元素置空,跳出迴圈
 10             for (int i = 0; i < ngroups; i++) {
 11                 if (groups[i] == g) {
 12                     ngroups -= 1;
 13                     System.arraycopy(groups, i + 1, groups, i, ngroups - i);
 14                     groups[ngroups] = null;
 15                     break;
 16                 }
 17             }
 18 
 19             // 喚醒在此物件上所有等待的執行緒
 20             if (nthreads == 0) {
 21                 notifyAll();
 22             }
 23             // 如果此執行緒組同時滿足以下條件,銷燬該執行緒組及其子組
 24             // 1. 是守護執行緒組
 25             // 2. 包含的執行緒數為0
 26             // 3. 未啟動執行緒數量為0
 27             // 4. 包含的執行緒組數為0
 28             if (daemon && (nthreads == 0) && (nUnstartedThreads == 0) && (ngroups == 0)) {
 29                 destroy();
 30             }
 31         }
 32     }
 33 
 34     // 將指定執行緒加入該執行緒組
 35     void add(Thread t) {
 36         synchronized (this) {
 37             if (destroyed) {
 38                 throw new IllegalThreadStateException();
 39             }
 40             if (threads == null) {
 41                 threads = new Thread[4];
 42             } else if (nthreads == threads.length) {
 43                 threads = Arrays.copyOf(threads, nthreads * 2);
 44             }
 45             threads[nthreads] = t;
 46             nthreads++;
 47             // 為了防止執行緒組被銷燬,未啟動執行緒數遞減
 48             nUnstartedThreads--;
 49         }
 50     }
 51 
 52     // 移除指定的執行緒
 53     private void remove(Thread t) {
 54         synchronized (this) {
 55             if (destroyed) {
 56                 return;
 57             }
 58             for (int i = 0; i < nthreads; i++) {
 59                 if (threads[i] == t) {
 60                     System.arraycopy(threads, i + 1, threads, i, --nthreads - i);
 61                     threads[nthreads] = null;
 62                     break;
 63                 }
 64             }
 65         }
 66     }
 67 
 68     // 獲得該執行緒組的名字
 69     public final String getName() {
 70         return name;
 71     }
 72 
 73     // 獲得該執行緒組的最大優先順序
 74     public final int getMaxPriority() {
 75         return maxPriority;
 76     }
 77 
 78     // 獲得該執行緒組的父執行緒組
 79     public final ThreadGroup getParent() {
 80         if (parent != null)
 81             parent.checkAccess();
 82         return parent;
 83     }
 84 
 85     // 判斷該執行緒組是否是守護執行緒組
 86     public final boolean isDaemon() {
 87         return daemon;
 88     }
 89 
 90     // 判斷該執行緒組是否被銷燬
 91     public synchronized boolean isDestroyed() {
 92         return destroyed;
 93     }
 94 
 95     // 設定該執行緒組的最大優先順序
 96     public final void setMaxPriority(int pri) {
 97         int ngroupsSnapshot;
 98         ThreadGroup[] groupsSnapshot;
 99 
100         synchronized (this) {
101             checkAccess();
102             // 判斷給定優先順序是否符合要求,不符合要求直接返回
103             if (pri < Thread.MIN_PRIORITY || pri > Thread.MAX_PRIORITY) {
104                 return;
105             }
106 
107             // 如果當前執行緒組沒有父執行緒組,最大優先順序就為給定的值
108             // 否則判斷父執行緒組最大優先順序和指定優先順序,取最小值為該執行緒組的最大優先順序
109             maxPriority = (parent != null) ? Math.min(pri, parent.maxPriority) : pri;
110 
111             // 獲取該執行緒子執行緒組的快照(如果存在的話
112             ngroupsSnapshot = ngroups;
113             if (groups != null) {
114                 groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
115             } else {
116                 groupsSnapshot = null;
117             }
118         }
119         // 遍歷該執行緒組的所有子執行緒組,遞迴將最大優先順序設定為指定值
120         for (int i = 0; i < ngroupsSnapshot; i++) {
121             groupsSnapshot[i].setMaxPriority(pri);
122         }
123     }
124 
125     // 設定該執行緒組是否是守護執行緒
126     public final void setDaemon(boolean daemon) {
127         checkAccess();
128         this.daemon = daemon;
129     }
130 
131     // 測試此執行緒組是否是指定執行緒組的祖先
132     public final boolean parentOf(ThreadGroup g) {
133         for (; g != null; g = g.parent) {
134             if (g == this) {
135                 return true;
136             }
137         }
138         return false;
139     }
140 
141     // 銷燬此執行緒組及其子組
142     public final void destroy() {
143         int ngroupsSnapshot;
144         ThreadGroup[] groupsSnapshot;
145         synchronized (this) {
146             checkAccess();
147             // 如果執行緒組已經銷燬或該執行緒組還有活動的執行緒,丟擲一個異常
148             if (destroyed || (nthreads > 0)) {
149                 throw new IllegalThreadStateException();
150             }
151             // 獲取子執行緒組的快照(如果存在的話)
152             ngroupsSnapshot = ngroups;
153             if (groups != null) {
154                 groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
155             } else {
156                 groupsSnapshot = null;
157             }
158 
159             // 如果該執行緒組存在父執行緒組,將各種屬性置空
160             if (parent != null) {
161                 destroyed = true;
162                 ngroups = 0;
163                 groups = null;
164                 nthreads = 0;
165                 threads = null;
166             }
167         }
168         // 迴圈遍歷子執行緒組,對每個子執行緒組進行遞迴處理
169         for (int i = 0; i < ngroupsSnapshot; i += 1) {
170             groupsSnapshot[i].destroy();
171         }
172 
173         // 如果一個執行緒組存在父執行緒組,從父執行緒組中移除該執行緒組
174         if (parent != null) {
175             parent.remove(this);
176         }
177     }
178 
179     // 獲得此執行緒組中活動的執行緒數
180     public int activeCount() {
181         int result;
182         int ngroupsSnapshot;
183         ThreadGroup[] groupsSnapshot;
184         synchronized (this) {
185             if (destroyed) {
186                 return 0;
187             }
188             result = nthreads;
189             ngroupsSnapshot = ngroups;
190             if (groups != null) {
191                 groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
192             } else {
193                 groupsSnapshot = null;
194             }
195         }
196         for (int i = 0; i < ngroupsSnapshot; i++) {
197             result += groupsSnapshot[i].activeCount();
198         }
199         return result;
200     }
201 
202     // 獲得此執行緒組中活動的執行緒組數
203     public int activeGroupCount() {
204         int ngroupsSnapshot;
205         ThreadGroup[] groupsSnapshot;
206         synchronized (this) {
207             if (destroyed) {
208                 return 0;
209             }
210             ngroupsSnapshot = ngroups;
211             if (groups != null) {
212                 groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
213             } else {
214                 groupsSnapshot = null;
215             }
216         }
217         int n = ngroupsSnapshot;
218         for (int i = 0; i < ngroupsSnapshot; i++) {
219             n += groupsSnapshot[i].activeGroupCount();
220         }
221         return n;
222     }
223 
224     // 將此執行緒組的有關資訊輸出到標準輸出流
225     public void list() {
226         list(System.out, 0);
227     }
228 
229     void list(PrintStream out, int indent) {
230         int ngroupsSnapshot;
231         ThreadGroup[] groupsSnapshot;
232         synchronized (this) {
233             for (int j = 0; j < indent; j++) {
234                 out.print(" ");
235             }
236             out.println(this);
237             indent += 4;
238             for (int i = 0; i < nthreads; i++) {
239                 for (int j = 0; j < indent; j++) {
240                     out.print(" ");
241                 }
242                 out.println(threads[i]);
243             }
244             ngroupsSnapshot = ngroups;
245             if (groups != null) {
246                 groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
247             } else {
248                 groupsSnapshot = null;
249             }
250         }
251         for (int i = 0; i < ngroupsSnapshot; i++) {
252             groupsSnapshot[i].list(out, indent);
253         }
254     }
255 
256     // 返回此此類的字串描述:類名+執行緒組名+最大優先順序
257     public String toString() {
258         return getClass().getName() + "[name=" + getName() + ",maxpri=" + maxPriority + "]";
259     }
260 
261     // 中斷執行緒組中所有執行緒和子執行緒組
262     public final void interrupt() {
263         int ngroupsSnapshot;
264         ThreadGroup[] groupsSnapshot;
265         synchronized (this) {
266             checkAccess();
267             // 中斷包含的執行緒
268             for (int i = 0; i < nthreads; i++) {
269                 threads[i].interrupt();
270             }
271             ngroupsSnapshot = ngroups;
272             if (groups != null) {
273                 groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
274             } else {
275                 groupsSnapshot = null;
276             }
277         }
278         // 遍歷子執行緒組,遞迴處理每一個子執行緒組
279         for (int i = 0; i < ngroupsSnapshot; i++) {
280             groupsSnapshot[i].interrupt();
281         }
282     }
283 
284     // 將執行緒組的所有活動執行緒複製到指定陣列中。如果存在第二個引數,第二個引數為true表示包含子組中的活動執行緒,預設包含子組中的所有活動執行緒數,
285     // 當給定的陣列不足以容納該執行緒組的活動執行緒數時,忽略額外的執行緒,因此,最好呼叫activeCount方法確定是否小於list的長度
286     public int enumerate(Thread list[]) {
287         checkAccess();
288         return enumerate(list, 0, true);
289     }
290 
291     public int enumerate(Thread list[], boolean recurse) {
292         checkAccess();
293         return enumerate(list, 0, recurse);
294     }
295 
296     private int enumerate(Thread list[], int n, boolean recurse);
297 
298     // 將執行緒組的所有活動子組複製到指定陣列中。如果存在第二個引數,第二個引數為true表示包含子組中的活動子組,預設包含子組中的所有活動子組,
299     // 當給定的陣列不足以容納該執行緒組的活動子組數時,忽略額外的子組,因此,最好呼叫activeGroupCount方法確定是否小於list的長度
300 
301     public int enumerate(ThreadGroup list[]) {
302         checkAccess();
303         return enumerate(list, 0, true);
304     }
305 
306     public int enumerate(ThreadGroup list[], boolean recurse) {
307         checkAccess();
308         return enumerate(list, 0, recurse);
309     }
310 
311     private int enumerate(ThreadGroup list[], int n, boolean recurse);
312 
313     // 允許Java虛擬機器在記憶體不足是掛起
314     @Deprecated
315     public boolean allowThreadSuspension(boolean b);
316 
317     // 停止此執行緒組中的所有執行緒,不安全
318     @Deprecated
319     public final void stop();
320 
321     // 掛起此執行緒組中的所有執行緒。 容易導致死鎖
322     @Deprecated
323     public final void suspend();
324 
325     // 繼續此執行緒組中的所有執行緒。容易導致死鎖
326     @Deprecated
327     public final void resume();
328 
329 }
View Code

執行緒Thread

  1 // 公開的建構函式本質上都是先呼叫四個引數的init方法,然後呼叫六個引數的私有init方法構造執行緒物件
  2 
  3 public Thread() {
  4     // 呼叫無參構造時設定執行緒的名字,然後呼叫四個引數的私有init方法,由init方法去呼叫六個引數的init方法
  5     init(null, null, "Thread-" + nextThreadNum(), 0);
  6 }
  7 
  8 // 構造一個新的Thread物件,使用指定的執行物件
  9 public Thread(Runnable target) {
 10     // 設定執行緒的名字,呼叫四個引數的init方法,由init方法去呼叫六個引數的init方法
 11     init(null, target, "Thread-" + nextThreadNum(), 0);
 12 }
 13 
 14 // 構造一個指定執行緒組,使用指定執行物件的Thread物件
 15 public Thread(ThreadGroup group, Runnable target) {
 16     init(group, target, "Thread-" + nextThreadNum(), 0);
 17 }
 18 
 19 // 構造一個指定執行緒名的Thread物件
 20 public Thread(String name) {
 21     init(null, null, name, 0);
 22 }
 23 
 24 // 構造一個指定執行緒組和名字的Thread物件
 25 public Thread(ThreadGroup group, String name) {
 26     init(group, null, name, 0);
 27 }
 28 
 29 // 構造一個具有指定執行物件和名字的Thread物件
 30 public Thread(Runnable target, String name) {
 31     init(null, target, name, 0);
 32 }
 33 
 34 // 構造一個具有指定執行緒組,執行物件和名字的Thread物件
 35 public Thread(ThreadGroup group, Runnable target, String name) {
 36     init(group, target, name, 0);
 37 }
 38 
 39 // 構造一個具有指定執行緒組,執行物件,名字和堆疊大小的Thread物件
 40 public Thread(ThreadGroup group, Runnable target, String name,
 41               long stackSize) {
 42     init(group, target, name, stackSize);
 43 }
 44 
 45 // 這個構造器不是公開的,他將建立一個
 46 Thread(Runnable target, AccessControlContext acc) {
 47         init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
 48 }
 49 
 50 // 公開的建構函式先呼叫這個方法
 51 private void init(ThreadGroup g, Runnable target, String name,
 52                       long stackSize) {
 53         init(g, target, name, stackSize, null, true);
 54 }
 55 
 56 private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {
 57         // 如果給定的執行緒名是null丟擲空指標異常
 58     if (name == null) {
 59     throw new NullPointerException("name cannot be null");
 60     }
 61         // 設定執行緒名
 62     this.name = name;
 63         // 獲取父執行緒
 64     Thread parent = currentThread();
 65         // 獲取安全管理器
 66     SecurityManager security = System.getSecurityManager();
 67         
 68         // 如果未指定執行緒所在的執行緒組
 69     if (g == null) {
 70             // 如果安全管理器存在,就使用安全管理器的方法返回當前執行緒的執行緒組
 71         if (security != null) {
 72                 g = security.getThreadGroup();
 73             }
 74         
 75             // 如果所屬的執行緒組還是沒有,就使用父執行緒的執行緒組作為該執行緒的執行緒組     
 76         if (g == null) {
 77          g = parent.getThreadGroup();
 78         }
 79          }
 80         // 判斷當前執行緒是否有許可權修改此g執行緒組,該方法時ThreadGroup的
 81         g.checkAccess();
 82 
 83         // 檢查是否有許可權
 84         if (security != null) {
 85             // 驗證是否可以構造該例項
 86             if (isCCLOverridden(getClass())) {
 87               security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);// 驗證是否有指定的執行時許可權 
 88             }
 89         }
 90          // 增加執行緒組中未啟動執行緒的數量。
 91         g.addUnstarted();
 92 
 93         // 設定執行緒相關屬性,獲取父執行緒的相關屬性作為該執行緒的相關屬性(如果未指定)
 94         this.group = g;
 95         this.daemon = parent.isDaemon();
 96         this.priority = parent.getPriority();
 97         if (security == null || isCCLOverridden(parent.getClass()))
 98             this.contextClassLoader = parent.getContextClassLoader();
 99         else
100             this.contextClassLoader = parent.contextClassLoader;
101         this.inheritedAccessControlContext =
102                 acc != null ? acc : AccessController.getContext();
103         this.target = target;
104         setPriority(priority);
105         if (inheritThreadLocals && parent.inheritableThreadLocals != null)
106             this.inheritableThreadLocals =
107                 ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
108         this.stackSize = stackSize;
109         tid = nextThreadID();
110 }

 ThreadGroup,Thread,Thread.State,Thread.UncaughtException之間的類圖

&n