執行緒的唯一標識(ID)是什麼?
資料庫裡頭,我們建表的時候通常唯一標識叫ID
,Thread物件也有ID,可以通過getId
來獲取。這個ID是自增長的,我們可以檢視Thread原始碼,下面是我截取出來的程式碼片段。
public class Thread implements Runnable {
/* For generating thread ID */
private static long threadSeqNumber;
private static int threadInitNumber;
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
}
從程式碼中可以看到有兩種ID,分別是threadSeqNumber
和threadInitNumber
。我來稍微解釋一下,threadSeqNumber是執行緒的ID,可以看到這個ID是同步遞增的,我們可以在Thread的init方法中看到,每個執行緒都會分配一個這樣的ID。
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) {
// 此處省略其它原始碼
/* Set thread ID */
tid = nextThreadID();
}
而threadInitNumber是當我們沒有給執行緒起名字的時候,預設會採用Thread-N
的格式給執行緒起名,這裡的N就是threadInitNumber
。從Thread原始碼中我們可以看到下面的建構函式,這裡只列出來兩個與之相關的構造。
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
public Thread(String name) {
init(null, null, name, 0);
}
很明顯,我們可以發現,如果我們採用這裡無參構造,會產生一個格式為Thread-N
的預設名稱,此時threadInitNumber
也會隨之遞增,如果我們採用有參的構造,threadInitNumber
就不會遞增。所以我們不要愚蠢的看到預設名稱後面的數字,就認為我們當前主執行緒下開啟了這麼多個執行緒,更不要愚蠢的認為這個數字就是執行緒的ID。這個數字跟ID和執行緒數沒半毛錢關係的。
當我們拿到執行緒的ID以後,就可以根據ID獲取到這個執行緒物件。
如下:
public static void main(String[] args) throws Exception {
// 構造一個執行緒並啟動,取名為"my-thread"
Thread myThread = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "my-thread");
myThread.start();
long myThreadId = myThread.getId();
System.out.println("my-thread執行緒ID為:" + myThreadId);
// 拿到當前執行緒下所有子執行緒,找出名稱為"my-thread"的執行緒並輸出該執行緒的ID
// 這串程式碼用到了activeCount和enumerate方法,在API的介紹中有詳細說明
Thread[] ts = new Thread[Thread.activeCount()];
Thread.enumerate(ts);
for(Thread t: ts) {
if(t.getId() == myThread.getId()) {
System.out.println("從主執行緒中找到名為my-thread的執行緒,執行緒名稱為:" + t.getName() + ", 狀態為: " + t.getState());
}
}
}
找遍了Thread的靜態方法,沒有找到可以直接通過ID或者NAME去獲取thread物件,最終所以採用了這種愚蠢的方式。我想說的是,無論這種方式是否最佳,但我根據ID拿到了子執行緒物件進而可以操作這個子執行緒。
注意,Thread.enumerate只能拿到非NEW和非TERMINATED狀態的子執行緒。所以這段程式碼可能沒有任何輸出。
最後總結一下:
threadSeqNumber
是執行緒的ID,可以通過執行緒物件的getId
方法來獲取。
(完)