HOWTO · Java
在 Java 中獲取執行緒 ID
本文將介紹在 Java 中獲取執行緒 id 的方法。
本頁內容
在 Java 中,對 Thread 物件呼叫 Thread.getId(),即可讀取該執行緒的識別碼。工作在 executor 中執行時,Thread.currentThread().getId() 會指出正在執行該工作的工作執行緒。以下範例展示這兩種情況;兩者取得的值都不是執行緒池或執行緒名稱的識別資訊。如果你已有 Thread 參照,請使用第一種方式;如果要在工作執行期間識別目前的工作執行緒,則在工作程式碼中使用第二種方式。
在 Java 中使用 Thread.getId() 取得執行緒 ID
建立一個 Thread 物件,再呼叫它的 getId() 方法,以 long 型別取得該物件的識別碼。第一個範例會建立兩個執行緒物件並讀取各自的 ID。範例不會啟動這些執行緒;讀取物件的識別碼不需要先啟動它們。執行階段會指派識別碼,其值可能因執行次數或環境而異,因此程式應使用執行時取得的值,不要依賴範例中的數字。當程式持有特定 Thread 的參照,且需要將它與其他執行緒物件區分時,這種方式很有用。
public class GetThreadID {
public static void main(String[] args) {
Thread thread1 = new Thread();
Thread thread2 = new Thread();
System.out.println("Thread 1 ID: " + thread1.getId());
System.out.println("Thread 2 ID: " + thread2.getId());
}
}
以下是某次執行的示意輸出:
Thread 1 ID: 12
Thread 2 ID: 13
以上數字 ID 僅供示意,實際值會因執行階段而異。由於範例沒有啟動這些執行緒,程式會依照兩個列印敘述的順序輸出物件 ID;其他執行次數或環境中的數字可能不同。
使用 Thread.currentThread().getId() 取得執行緒池中目前工作執行緒的 ID
提交至 executor 的工作會由其中一個工作執行緒執行。在工作內呼叫 Thread.currentThread().getId(),即可取得目前正在執行它的工作執行緒 ID。這是工作執行緒的 ID,不是 executor 或執行緒池的識別資訊。固定大小的執行緒池會重複使用工作執行緒,因此不同工作可能回報相同的工作執行緒 ID。排程會決定各項工作由哪個工作執行緒處理,因此工作順序與數字 ID 都可能變動。診斷是哪個執行緒執行某項工作時,這項區別很重要:回傳的數字表示當下執行工作的工作執行緒,而不是負責排程的 executor。
範例會提交五項工作、列印每項工作的編號與工作執行緒 ID,然後關閉 executor。shutdown() 會停止接收新工作,同時讓已提交的工作繼續完成。awaitTermination 最多等待一分鐘讓工作完成,不會忙碌輪詢。如果工作耗時超過這段時間,程式會回報等待逾時;關閉要求已送出,因此佇列中的工作仍可繼續執行。在正式環境的程式碼中,應選擇符合應用程式工作需求的逾時時間,並決定工作未能及時完成時該如何處理。如果需要為特定 Java 版本選擇 API 細節,請參閱該版本的文件;此處未指定目標版本。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class GetThreadID {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i = 1; i <= 5; i++) {
final int taskNumber = i;
executor.execute(() -> {
long workerId = Thread.currentThread().getId();
System.out.println("Task " + taskNumber + " ran on worker ID " + workerId);
});
}
executor.shutdown();
boolean finished = executor.awaitTermination(1, TimeUnit.MINUTES);
System.out.println(finished ? "All tasks finished" : "Wait timed out");
}
}
以下是某次執行的示意輸出;工作順序與數字 ID 會因執行階段而異:
Task 2 ran on worker ID 13
Task 3 ran on worker ID 13
Task 4 ran on worker ID 13
Task 5 ran on worker ID 13
Task 1 ran on worker ID 12
All tasks finished
如果你的目標是識別正在執行該工作的工作執行緒,請在工作內呼叫此方法。在其他位置呼叫時,取得的是執行該段程式碼的執行緒。由於執行緒池可能重複使用工作執行緒,且排程方式也可能不同,請將輸出視為單次執行的結果,不要把工作編號與工作執行緒 ID 的對應關係當成固定不變。