1. 程式人生 > >多執行緒--this和Thread.currentThread()詳解

多執行緒--this和Thread.currentThread()詳解

在看多執行緒程式設計核心技術的時候,有一段程式碼讓我很困惑,所以在這裡記錄一下。
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);
    }