Java多線程 - 線程的唯一標識(ID)是什么?(轉)


原文地址: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,分別是threadSeqNumberthreadInitNumberthreadSeqNumber是線程的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狀態的子線程。所以這段代碼可能沒有任何輸出。

(完)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM