public class SynchThread1 extends Thread {
SynchThread1 st;
SynchThread1() {}
SynchThread1(SynchThread1 s) {
st = s;
}
public void run() {
st.show();
}
synchronized void show() {
for (int i = 0; i < 5; i++)
System.out.print(Thread.currentThread().getName() + " "); //replace here
}
public static void main(String[] args) {
SynchThread1 s1 = new SynchThread1();
Thread t1 = new SynchThread1(s1);
Thread t2 = new SynchThread1(s1);
Thread t3 = new SynchThread1(s1);
s1.setName("t0");
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
t1.start();
t2.start();
t3.start();
}
}
上述代码的输出为:
t1 t1 t1 t1 t1 t3 t3 t3 t3 t3 t2 t2 t2 t2 t2
但是如果我仅用getName()
替换Thread.currentThread().getName()
,则输出为:
t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0
请解释为什么会发生这种情况。
因为Thread.currentThread().getName()
会获取当前正在运行的线程的名称,但getName()
解析为 st.getName()
,并且st
始终是您的第一个线程实例。
为什么getName()
决心st.getName()
?因为:
-
在构造第二个到第四个线程期间,将第一个线程作为参数传入,并将其保存在实例成员
st
中。 -
线程的
run
方法调用st.show()
,因此它们始终在第一个线程上调用show
。(如果你曾经启动过第一个线程,你会在那里得到一个 NPE,因为第一个线程的st
成员永远不会被赋予非null
值。 -
在
show
内,this
因此st
(第一个线程(。非限定实例方法调用使用this
作为其实例,this
是第一个线程。