在自学Thread的时候,遇到一个疑惑。 代码如下:
public class CurrentThreadExt extends Thread{
public CurrentThreadExt(){
System.out.println("CurrentThreadExt --------- begin");
System.out.println("Thread.currentThread().getName() = " + Thread.currentThread().getName());
System.out.println("this.getName() = " + this.getName());
System.out.println("CurrentThreadExt --------- end");
}
public void run(){
System.out.println("run --------- begin");
System.out.println("Thread.currentThread().getName() = " + Thread.currentThread().getName());
System.out.println("this.getName() = " + this.getName());
System.out.println("run --------- end");
}
}
在main方法中直接调用CurrentThreadExt ,此时结果很正常
CurrentThreadExt currentThread = new CurrentThreadExt();
currentThread.setName("xugc"); //修改currentThread的name属性为xugc
currentThread.start(); //currentThread线程加入调度,等待执行run方法
得到结果:
CurrentThreadExt --------- begin
Thread.currentThread().getName() = main //调用构造函数时,还在main线程里
this.getName() = Thread-0 //this表示的是currentThread对象
CurrentThreadExt --------- end
run --------- begin
Thread.currentThread().getName() = xugc //执行run方法时,已经进入了currentThread线程里
this.getName() = xugc //this表示的是currentThread线程
run --------- end
然而,把currentThread当做参数传入Thread(Runnable runnable)时,就有点让人疑惑了。
CurrentThreadExt currentThread = new CurrentThreadExt(); //新建currentThread对象
Thread t1 = new Thread(currentThread); //新建Thread对象,
currentThread.setName("gg"); //currentThread的name属性设置为gg
t1.setName("xugc"); //t1的name属性设置为xugc
t1.start(); //t1加入调度,等待执行t1.run
得到结果:
CurrentThreadExt --------- begin
Thread.currentThread().getName() = main // 此时还是在main线程内
this.getName() = Thread-0 // this代表的currentThread对象
CurrentThreadExt --------- end
run --------- begin
Thread.currentThread().getName() = xugc // 现在执行的是t1线程,所以name显示为xugc
this.getName() = gg // 这里为什么显示的是gg,currentThread的name?
run --------- end
如上,有问题的就是run方法里的this.getName(),为什么显示的是gg而不是xugc?明明是t1.start()啊?其实这个问题理解起来不难,就是得找出this到底代表的是哪个对象。
首先t1.start()执行完了以后,t1线程加入调度,最终执行t1.run() 方法,查看Thread类run方法的源码。如下:
@Override
public void run() {
if (target != null) {
target.run();
}
}
判断t1.target是不是null,如果不是,执行t1.targer.run(),那么t1.target是什么呢?
在初始化t1时候,调用的Thread(Runnable runnable)构造函数,看一下这个方法的源码。如下:
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null);
}
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
....
this.target = target;
....
}
省去无关的代码,t1.target实际上指向的是currentThread对象,也就是说t1.target.run 就是currentThread.run,所以run方法中显示的this.getName就是currentThread的name属性了。
后来想想,还有另外一种理解思路,既然this都是写在CurrentThreadExt类里的,那么实际运行的时候,this肯定指向的是CurrentThreadExt类的对象。