今天看了多线程的书,作者阐述了两者有时不一样,但是并没有说明原因,好奇,自己对着代码改了一下。
解开第七行注释,注释第六行,使用自己定义的构造器,结果是这样的:
可以看到第一种情况使用了Thread的构造器,this.getName()却指向之前线程(即构造器中的参数线程),
这是线程类,这里我自己添加了一个构造方法用来基于本线程创建新线程(说法可能不太对),
package test;
public class CountOprate extends Thread {
CountOprate() {
System.out.println("CountOprate --- 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.isAlive() = " + this.isAlive());
System.out.println("CountOprate --- end ");
}
CountOprate(Thread target){//自己写的
super(target);
System.out.println("CountOprate2 --- 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.isAlive() = " + this.isAlive());
System.out.println("CountOprate2 --- 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("this.getName() = " + this.getName());
System.out.println("this.isAlive() = " + this.isAlive());
System.out.println("run --- end ");
}
}
这里是test类,用于测试,这里先来看注释掉第七行的结果,这是正常的方式,调用Thread的构造方法
package test;
public class CountOprateTest {
public static void main(String[] String) throws InterruptedException {
CountOprate co = new CountOprate();
Thread t1 = new Thread(co);
// CountOprate t1 = new CountOprate(co);
System.out.println("main begin t1 isAlive " + t1.isAlive());
t1.start();
System.out.println("main end t1 isAlive " + t1.isAlive());
// co.start();
System.out.println("co isAlive " + co.isAlive());
}
}
结果为:
CountOprate --- begin
Thread.currentThread().getName() = main
Thread.currentThread().isAlive() = true
this.getName() = Thread-0
this.isAlive() = false
CountOprate --- end
main begin t1 isAlive false
main end t1 isAlive true
co isAlive false
run --- begin
Thread.currentThread().getName() = Thread-1
Thread.currentThread().isAlive() = true
this.getName() = Thread-0
this.isAlive() = false
run --- end
解开第七行注释,注释第六行,使用自己定义的构造器,结果是这样的:
CountOprate --- begin
Thread.currentThread().getName() = main
Thread.currentThread().isAlive() = true
this.getName() = Thread-0
this.isAlive() = false
CountOprate --- end
CountOprate2 --- begin
Thread.currentThread().getName() = main
Thread.currentThread().isAlive() = true
this.getName() = Thread-1
this.isAlive() = false
CountOprate2 --- end
main begin t1 isAlive false
main end t1 isAlive true
co isAlive false
run --- begin
Thread.currentThread().getName() = Thread-1
Thread.currentThread().isAlive() = true
this.getName() = Thread-1
this.isAlive() = true
run --- end
可以看到第一种情况使用了Thread的构造器,this.getName()却指向之前线程(即构造器中的参数线程),
而第二种情况使用了自己的构造方法,则this与Thread.currentThread()一致,
这是为什么呢???
我们来一层一层找,这是Thread构造方法
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);
}
public void run() {
if (target != null) {
target.run();
}
}
我们好像发现了什么,,,这里的构造器,是创建线程,直接传递target,之后run方法就更省力了,target.run(),
这不就是直接调用target线程的run方法吗,那this指向target线程就理所当然了
看回来,我自己线程类里面那个构造器虽然也是调用的Thread(Runnable target),但是run方法调用权由Thread父类调用改为了CountOprate类自己调用,所以this指向是正常的
CountOprate(Thread target){
super(target);
System.out.println("CountOprate2 --- 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.isAlive() = " + this.isAlive());
System.out.println("CountOprate2 --- end ");
}
详细来说, 第一种调用的时候作为一个Thread类而不是CountOprate类,调用的是Thread的run方法,而Thread的run方法是直接使用target调用target线程的run方法
所以this指向target线程 第二种方式:调用时作为一个CountOprate类,调用了CountOprate的run方法,所以this指向了这个线程,与Thread.currentThread一致