Thread.currentThread().getName() 和 this.getName()區別詳解
currentThread的詳解
currentThread方法是Thread類的一個靜態方法,用來獲取當前執行的程式碼段,正在被哪個執行緒呼叫。我們先來看一眼原始碼。
是一個native方法。直接與系統層面做互動。
下面看一段程式碼
public static void main(String[] args) {
String name = Thread.currentThread().getName();
System.out.println(name);
}
輸出的結果為main。
為什麼為main呢?
java的專案在啟動的時候,會創立一個程序,這個程序同樣也是一個執行緒,在java裡面他就叫做main執行緒。他的名字在設定的時候就是main。我們可以看到上面的程式碼就是在main方法下執行的,也就是由main執行緒來執行,所以我們打印出來的名字是main。
建立一個新的執行緒
來看下面的一行程式碼,我們建立一個新的執行緒,並且線上程建立的構造方法和其實際執行的run方法內,增加打印出當前執行執行緒的名稱。
public class TestThread extends Thread { public TestThread() { System.out.println("構造方法:" + Thread.currentThread().getName()); } @Override public void run() { System.out.println("run方法:" + Thread.currentThread().getName()); } public static void main(String[] args) { TestThread testThread = new TestThread(); testThread.start(); } }
我們執行一下,看到結果
構造方法:main
run方法:Thread-0
如何理解上述的情況呢?
我們先來看構造方法這一行。
TestThread testThread = new TestThread();
這裡我們只是聲明瞭一個執行緒物件類,這個新的執行緒沒有建立也沒有啟動,我們僅僅把它理解為一個普通物件即可。那麼由於是在main方法裡面,那麼執行他的一定是main執行緒,所以可以看到構造方法輸出的結果是main。
再來看start方法裡面,為什麼變成了thread-0了呢。
我們知道java的多執行緒建立的一種方式就是繼承thread類。然後實現裡面的run方法。這樣當執行緒start的時候,就會呼叫內部的start0的本地方法,實際就是會執行run的實現方法。當run方法執行的時候,一定是由我們建立的執行緒去執行的,而不是main執行緒,所以我們就可以得知打印出來的是新執行緒的名字thread0。
為什麼新執行緒的名字為thread0呢?
我們是採用繼承thread類的形式來建立執行緒的,那麼在我們構造的時候,一定會執行父類的構造方法。我們是一個空參構造,那麼我們就要看下父類的空參構造是什麼樣的。看一下原始碼
可以看到,裡面有一個name引數,已經給我們拼接了一個thread-後面是加了一個變數,我們繼續看看這個變數是什麼
一個同步的靜態方法,再來看看變數的值。
一個靜態的int型變數,由此我們知道int的初始值就是0。我們先獲取到了0然後又執行了++。其他執行緒再次初始化的時候就是從1開始了。因為加了同步鎖的關鍵字,我們不用害怕資料會亂掉。
所以我們就知道了新執行緒的名字為thread-0的來源。
再看一種帶this的情況
public class TestThread extends Thread {
public TestThread() {
System.out.println("構造方法開始!");
System.out.println("構造方法:" + Thread.currentThread().getName());
System.out.println("構造方法的this名稱:" + this.getName());
System.out.println("構造方法結束!");
}
@Override
public void run() {
System.out.println("run方法開始!");
System.out.println("run方法:" + Thread.currentThread().getName());
System.out.println("run方法的this名稱:" + this.getName());
System.out.println("run方法結束!");
}
public static void main(String[] args) {
TestThread testThread = new TestThread();
testThread.start();
}
}
執行的結果如下:
構造方法開始!
構造方法:main
構造方法的this名稱:Thread-0
構造方法結束!
run方法開始!
run方法:Thread-0
run方法的this名稱:Thread-0
run方法結束!
我們發現構造的this名稱 為thread-0。這個不難理解,this指的是當前物件的名稱。因為我們的執行緒在初始化的時候有了name,所以是thread-0。
建立的執行緒setName的情況
public class TestThread extends Thread {
public TestThread() {
System.out.println("構造方法開始!");
System.out.println("構造方法:" + Thread.currentThread().getName());
System.out.println("構造方法的this名稱:" + this.getName());
System.out.println("構造方法結束!");
}
@Override
public void run() {
System.out.println("run方法開始!");
System.out.println("run方法:" + Thread.currentThread().getName());
System.out.println("run方法的this名稱:" + this.getName());
System.out.println("run方法結束!");
}
public static void main(String[] args) {
TestThread testThread = new TestThread();
testThread.setName("test");
testThread.start();
}
}
看一下執行的結果
構造方法開始!
構造方法:main
構造方法的this名稱:Thread-0
構造方法結束!
run方法開始!
run方法:test
run方法的this名稱:test
run方法結束!
這裡有人可能就要問了,為啥構造方法的this名稱為thread-0。實際run的時候就變為test了呢。
這是因為我們在構造物件的時候,物件還不完整,沒有執行到setName這一步。所以二者不一致。
最後看一段複雜的程式碼
public class TestThread extends Thread {
public TestThread() {
System.out.println("構造方法開始!");
System.out.println("構造方法:" + Thread.currentThread().getName());
System.out.println("構造方法的this名稱:" + this.getName());
System.out.println("構造方法結束!");
}
@Override
public void run() {
System.out.println("run方法開始!");
System.out.println("run方法:" + Thread.currentThread().getName());
System.out.println("run方法的this名稱:" + this.getName());
System.out.println("run方法結束!");
}
public static void main(String[] args) {
TestThread testThread = new TestThread();
Thread thread = new Thread(testThread);
System.out.println("新執行緒thread的名稱:" + thread.getName());
thread.setName("test");
thread.start();
}
}
可以看到如下的結果
構造方法開始!
構造方法:main
構造方法的this名稱:Thread-0
構造方法結束!
新執行緒thread的名稱:Thread-1
run方法開始!
run方法:test
run方法的this名稱:Thread-0
run方法結束!
我們根據結果來看,構造方法的列印,和上面解釋的如出一轍。我們重點關注一下新執行緒的列印,這裡為什麼是1呢,因為我們上面初始化0之後已經++所以為1。
run方法為test是因為我們實際執行的執行緒Thread thread = new Thread(testThread);所以我們獲取到的名稱是thread的名稱為test。
那麼run方法的this名稱為什麼是thread-0呢。因為this.getName獲取到的是當前物件的名稱。我們的當前物件是TestThread。他的執行緒名稱從未被改變過,所以我們拿到了thread-0。
總結
currentThread的getName代表當前執行執行緒的名稱,this.getName代表物件的名稱。this.getName()實際上返回的是target.getName(),而Thread.currentThread().getName()實際上是thead.getName()。
作者:經典雞翅 微信公眾號:經典雞翅 如果你想及時得到個人撰寫文章,純java的面試資料或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號)。