简体   繁体   English

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

[英]Thread object constructed by runnable overrides the run method

Given this sample code: 鉴于此示例代码:

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

why is the output Dog and not Cat?? 为什么输出狗而不是猫?

The implementation of run in Thread simply calls the Runnable provided in the constructor, if there is one. run in Thread的实现只是调用构造函数中提供的Runnable (如果有的话)。 You're overriding that code, so if the new thread simply has its run method called regardless, the Runnable is ignored. 您正在覆盖该代码,因此如果新线程只是调用其run方法,则忽略Runnable Of course, you should be able to look at the source code to check that... (I've just done so, and while I'm not going to post the source here, it does exactly what I've described.) 当然,您应该能够查看源代码来检查...(我刚刚这样做了,虽然我不打算在这里发布源代码,但它完全按照我的描述进行。)

What you've really exposed is an encapsulation problem - Thread shouldn't have these different, potentially conflicting, ways of saying what the thread should do. 你真正暴露的是封装问题 - Thread 不应该有这些不同的,可能相互矛盾的方式来说明线程应该做什么。 Basically, you should almost never extend Thread directly. 基本上,你几乎应该直接扩展Thread Just because it's been designed badly doesn't mean you have to abuse that poor design ;) 仅仅因为它设计得很糟糕并不意味着你必须滥用那种糟糕的设计;)

EDIT: This is actually documented, in a somewhat roundabout way. 编辑:这实际上是以一种稍微迂回的方式记录的。 start() is documented as: start()记录为:

Causes this thread to begin execution; 导致此线程开始执行; the Java Virtual Machine calls the run method of this thread. Java虚拟机调用此线程的run方法。

And run() is documented as: run()记录为:

If this thread was constructed using a separate Runnable run object, then that Runnable object's run method is called; 如果使用单独的Runnable运行对象构造此线程,则调用该Runnable对象的run方法; otherwise, this method does nothing and returns. 否则,此方法不执行任何操作并返回。

So the run() method is called as per start() , but you've overridden run() , which is the only method which will call the Runnable provided in the constructor. 因此run()方法按照start()调用,但是你重写了run() ,这是调用构造函数中提供的Runnable唯一方法。

Note that if you'd overridden the method like this: 请注意,如果您重写了这样的方法:

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

Then the output would be "CatDog". 然后输出将是“CatDog”。

You have overridden Thread.run so that it doesn't execute the runnable. 您已重写Thread.run以便它不执行runnable。 Instead it just prints "Dog". 相反,它只是打印“狗”。

It is because the function run() is overridden. 这是因为函数run()被覆盖了。 And t call this function: t调用这个函数:

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

You will get the o/p as cat when you execute r.start() Which will call the function 当你执行r.start()时,你将获得o / p作为cat ,这将调用该函数

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

Taking a look at the source code for java.lang.Thread : 看一下java.lang.Thread的源代码:

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

target is the Runnable field in the Thread that the Thread(Runnable) constructor uses to assign your r variable. targetThread(Runnable)构造函数用于分配r变量的Thread中的Runnable字段。 When you override the run method in the Thread , you're changing the behavior of run to call 当你在Thread覆盖run方法时,你正在改变run to call的行为

System.out.print("Dog");

instead of calling 而不是打电话

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

This is an anonymous class and you are redefining/overriding run . 这是一个匿名类,您正在重新定义/覆盖run Are you using the passed-in Runnable inside your run ? 你在run使用传入的Runnable吗? No you don't. 不,你没有。 So the question is, why did you expect it to print Cat ? 所以问题是,你为什么期望它打印Cat

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM