由runnable构造的线程对象会覆盖run方法

时间:2012-09-05 16:23:34

标签: java scjp

鉴于此示例代码:

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();

为什么输出Dog而不是Cat ??

5 个答案:

答案 0 :(得分:7)

runThread的实施只会调用构造函数中提供的Runnable(如果有)。您正在覆盖该代码,因此如果新线程只是调用其run方法,则忽略Runnable。当然,您应该能够查看源代码来检查...(我刚刚这样做了,虽然我不打算在这里发布源代码,但它完全按照我的描述进行。)

你真正暴露的是封装问题 - Thread 不应该有这些不同的,可能相互矛盾的方式来说明线程应该做什么。基本上,你几乎永远不会直接扩展Thread。仅仅因为它设计得很糟糕并不意味着你必须滥用那种糟糕的设计;)

编辑:这实际上是以一种稍微迂回的方式记录的。 start()记录为:

  

使该线程开始执行; Java虚拟机调用此线程的run方法。

run()记录为:

  

如果使用单独的Runnable运行对象构造此线程,则调用该Runnable对象的run方法;否则,此方法无效并返回。

因此,run()方法按start()调用,但您已覆盖run(),这是唯一方法,它将调用{{} 1}}在构造函数中提供。

请注意,如果你覆盖了这样的方法:

Runnable

然后输出将是“CatDog”。

答案 1 :(得分:3)

您已覆盖Thread.run,因此它不会执行runnable。相反,它只是打印“狗”。

答案 2 :(得分:0)

这是因为覆盖了函数run()t调用此函数:

public void run() {
System.out.print("Dog");
}

当您执行cat时,您将获得r.start()的o / p将调用该函数

 public void run() {
    System.out.print("Cat");
  }

答案 3 :(得分:0)

查看java.lang.Thread的源代码:

public void run() {
    if (target != null) {
        target.run();
    }
}

targetRunnable中的Thread字段,Thread(Runnable)构造函数用于分配r变量。当您覆盖run中的Thread方法时,您正在更改run的行为以致电

System.out.print("Dog");

而不是打电话

if (target != null) {
    target.run();
}

答案 4 :(得分:-1)

这是一个匿名类,您正在重新定义/覆盖run。您是否在Runnable内使用了传入的run?不,你没有。所以问题是,为什么你希望它打印Cat

 new Thread(r) {
  public void run() {
    System.out.print("Dog");
  }
};