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
但如果我仅将Thread.currentThread().getName()
替换为getName()
,则输出为:
t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0
请解释为什么会这样。
答案 0 :(得分:4)
因为Thread.currentThread().getName()
为您提供当前正在运行的线程的名称,但getName()
解析为st.getName()
,st
始终是您的第一个线程实例。
为什么getName()
会解析为st.getName()
?这是因为:
在构建第二个到第四个线程的过程中,将第一个线程作为参数传递,并将其保存在实例成员st
中。
线程的run
方法调用st.show()
,因此他们总是在第一个线程上调用show
。 (如果你曾经开始过第一个主题,你就会在那里获得一个NPE,因为第一个主题的st
成员从未被赋予非null
值。)
在show
内,this
因此是st
(第一个主题)。非限定实例方法调用使用this
作为其实例,this
是第一个线程。