原文地址:https://blog.csdn.net/u012627861/article/details/82904600
結論
threadSeqNumber
是線程的ID,可以通過線程對象的getId
方法來獲取。
分析
數據庫里頭,我們建表的時候通常唯一標識叫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++;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
從代碼中可以看到有兩種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();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
而threadInitNumber是當我們沒有給線程起名字的時候,默認會采用Thread-N
的格式給線程起名,這里的N就是threadInitNumber
。從Thread源碼中我們可以看到下面的構造函數,這里只列出來兩個與之相關的構造。
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
public Thread(String name) {
init(null, null, name, 0);
}
- 1
- 2
- 3
- 4
- 5
- 6
很明顯,我們可以發現,如果我們采用這里無參構造,會產生一個格式為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());
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
找遍了Thread的方法,沒有找到可以直接通過ID或者NAME去獲取thread對象的方法,最終采用了這種拙劣的方式。無論這種方式是否最佳,我們根據ID拿到了子線程對象進而可以操作這個子線程。
注意,Thread.enumerate只能拿到非NEW和非TERMINATED狀態的子線程。所以這段代碼可能沒有任何輸出。
(完)