多執行緒--this和Thread.currentThread()詳解
阿新 • • 發佈:2018-11-13
在看多執行緒程式設計核心技術的時候,有一段程式碼讓我很困惑,所以在這裡記錄一下。
public class isalive { public static void main(String[] args) { // TODO Auto-generated method stub //Thread.currentThread().getName(); CountOperate countOperate=new CountOperate(); Thread t1=new Thread(countOperate); System.out.println("main begin t1 isalive "+t1.isAlive()); t1.setName("a"); t1.start(); System.out.println("main end "+t1.isAlive()); } } class CountOperate extends Thread{ public CountOperate(){ System.out.println("建構函式begin"); System.out.println("Thread.currentThread().getName() "+Thread.currentThread().getName()); System.out.println("Thread.currentThread().isAlive() "+Thread.currentThread().isAlive()); System.out.println("this.getname "+this.getName()); System.out.println("this.Alive "+this.isAlive()); System.out.println("測試:"+Thread.currentThread().getName()==this.getName());//新增的程式碼,為了測試是否相等 System.out.println("建構函式end "); } public void run(){ System.out.println("run begin"); System.out.println("Thread.currentThread().getName() "+Thread.currentThread().getName()); System.out.println("Thread.currentThread().isAlive() "+Thread.currentThread().isAlive()); System.out.println("測試:"+Thread.currentThread().getName()==this.getName());//為了測試是否相等 System.out.println("this.getname "+this.getName()); System.out.println("this.Alive "+this.isAlive()); System.out.println("run end"); } }
問題就是這邊的Thread.currentThread()和this有上面不同,我們先看一下執行之後的輸出。
首先從第2,3行輸出可以知道,countoperate的建構函式是在主執行緒中執行的,這個沒有疑問。
第3,4行輸出了thread-0,和false,Thread.currentThread()和this也並不是一個引用,因為this指向的是countoperate物件例項,該例項繼承thread,可以呼叫其中的getname(),isalive()方法。然後我就想知道為什麼它這邊this.getname()為什麼會拿出個thread-0出來。我們來看原始碼。
首先是thread的建構函式
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
private static int threadInitNumber;//執行緒的id也就是通過這個靜態變數來設定的。
nextThreadNum()方法
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
在進去Init()方法,因為這個方法裡面東西很多,我們只看我們需要的,name引數
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
this.target=target;
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
this.name = name.toCharArray();//在這裡將傳入的引數賦值給name,也就是執行緒的名稱,在通過getname()來獲取。
繼續往下看,從run函式裡面的輸出可以知道,當countoperate作為引數傳給t1執行緒,t1執行緒開啟時,這時候this指向的還是new countoperate的執行緒例項,而不是執行緒t1,為什麼呢?明明是用執行緒t1開啟呼叫run方法啊。
還是要看thread原始碼中另一個建構函式,countoperate作為target引數傳給這個執行緒,當執行t1.run()的時候,本質上呼叫還是target.run().所有this,getname()得到的還是thread-0.
public void run() {
if (target != null) {
target.run();
}
}
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}