5

鉴于此示例代码:

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

为什么输出是狗而不是猫?

4

5 回答 5

7

runin的实现Thread只是调用Runnable构造函数中提供的,如果有的话。您正在覆盖该代码,因此如果新线程只是简单地调用其run方法,Runnable则忽略 。当然,您应该能够查看源代码以检查...(我刚刚这样做了,虽然我不打算在这里发布源代码,但它完全符合我的描述。)

你真正暴露的是一个封装问题——Thread 不应该有这些不同的、潜在的冲突的方式来表达线程应该做什么。基本上,您几乎应该直接扩展Thread。仅仅因为它的设计很糟糕并不意味着你必须滥用那个糟糕的设计;)

编辑:这实际上以某种迂回的方式记录在案。start()记录为:

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

run()记录为:

如果该线程是使用单独的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,此方法不执行任何操作并返回。

因此,该run()方法按 per 调用start(),但是您已经覆盖run()了 ,这是唯一将调用Runnable构造函数中提供的方法的方法。

请注意,如果您重写了这样的方法:

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

然后输出将是“CatDog”。

于 2012-09-05T16:27:26.073 回答
3

您已被覆盖Thread.run,因此它不会执行可运行文件。相反,它只打印“狗”。

于 2012-09-05T16:26:12.630 回答
0

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

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

cat您将在执行时获得 o/pr.start()将调用该函数

 public void run() {
    System.out.print("Cat");
  }
于 2012-09-05T16:27:04.953 回答
0

看一下源代码java.lang.Thread

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

target是构造函数用来分配变量的Runnable字段。当您覆盖 中的方法时,您正在更改调用的行为ThreadThread(Runnable)rrunThreadrun

System.out.print("Dog");

而不是打电话

if (target != null) {
    target.run();
}
于 2012-09-05T16:30:10.067 回答
-1

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

 new Thread(r) {
  public void run() {
    System.out.print("Dog");
  }
};
于 2012-09-05T16:31:56.560 回答