给定此示例代码:
Runnable r = new Runnable() {
public void run() {
System.out.print("Cat");
}
};
Thread t = new Thread(r) {
public void run() {
System.out.print("Dog");
}
};
t.start();
为什么输出的是狗而不是猫??
run
在Thread
中的实现只需调用构造函数中提供的Runnable
(如果有)。您正在重写该代码,因此,如果新线程只调用其run
方法,则忽略Runnable
。当然,您应该能够查看源代码来检查。。。(我刚刚这么做了,虽然我不打算在这里发布消息来源,但它正是我所描述的。)
您真正暴露的是一个封装问题-Thread
不应该有这些不同的、潜在冲突的方式来说明线程应该做什么。基本上,您几乎不应该直接扩展Thread
。仅仅因为它设计得不好并不意味着你必须滥用糟糕的设计;)
编辑:这实际上是以一种迂回的方式记录的。start()
记录为:
使此线程开始执行;Java虚拟机调用该线程的run方法。
run()
记录为:
如果这个线程是使用单独的Runnable运行对象构建的,那么会调用该Runnable对象的run方法;否则,此方法不执行任何操作并返回。
因此,run()
方法是根据start()
调用的,但您已经重写了run()
,这是将调用构造函数中提供的Runnable
的仅的方法。
请注意,如果您覆盖了这样的方法:
Thread t = new Thread(r) {
public void run() {
super.run();
System.out.print("Dog");
}
};
那么输出将是"CatDog"。
您已经重写了Thread.run
,因此它不会执行可运行的。相反,它只是打印"狗"。
查看java.lang.Thread
:的源代码
public void run() {
if (target != null) {
target.run();
}
}
target
是Thread
中的Runnable
字段,Thread(Runnable)
构造函数用于分配r
变量。当您在Thread
中重写run
方法时,您正在将run
的行为更改为调用
System.out.print("Dog");
而不是调用
if (target != null) {
target.run();
}
这是因为函数run()
被重写了。t
调用此函数:
public void run() {
System.out.print("Dog");
}
当你执行r.start()
时,你会得到作为cat
的o/p,它会调用函数
public void run() {
System.out.print("Cat");
}
这是一个匿名类,您正在重新定义/覆盖run
。您是否在run
中使用传入的Runnable
?不,你没有。所以问题是,你为什么期望它打印Cat
?
new Thread(r) {
public void run() {
System.out.print("Dog");
}
};