1. 程式人生 > >執行緒的唯一標識(ID)是什麼?

執行緒的唯一標識(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,分別是threadSeqNumberthreadInitNumber。我來稍微解釋一下,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方法來獲取。

(完)