由runnable构造的线程对象重写run方法



给定此示例代码:

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

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

runThread中的实现只需调用构造函数中提供的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();
    }
}

targetThread中的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");
  }
};

最新更新