将 Runnable 实例传递给 Thread 调用 Thread 的 subclass 的 运行() 而不是 Runnable class 的 运行()

Passing a Runnable instance to Thread calls run() of Thread's subclass instead of run() of Runnable class

我有如下三个 classes :

1.ThreadInstance

public class ThreadInstance extends Thread {
    public ThreadInstance() 
    {
    }
    public ThreadInstance(RunnableInstance r) {
        super(r);
    }
    public void run() {
        System.out.println("|Extend|");
    }
}

2.RunnableInstance

public class RunnableInstance implements Runnable {
    public void run() {
        System.out.println("|Implement|");
    }
}

3.Client

public class Client{
    public static void main(String[] args) {
        new ThreadInstance(new RunnableInstance()).start();
    }
}

OUTPUT 打印|扩展|而不是 |实施|

在客户端class中,一个线程是通过传递一个运行nable实例来创建的。所以当这个线程运行时,应该调用Runnableclass(RunnableInstance)的运行()方法。但是在上面的例子中,调用了 ThreadInstance 的 运行() 方法。

我不太明白这背后的原因。任何人都可以说明我在这里缺少什么。我还检查了 Thread class 的 运行() 方法,发现如果检查 运行nable 实例是否不为 null,则它从 Runnable 运行() 调用方法 class。

i checked the run() method of Thread class and found that […] it calls run() method from Runnable class

您已覆盖 run 方法,因此您的 ThreadInstance 不再执行此操作。

您需要选择一个。 覆盖 Thread 中的 run 传递 Runnable。两者都不是。

从技术上讲,可以执行以下操作:

public class ThreadInstance extends Thread {
    public ThreadInstance() {}
    public ThreadInstance(RunnableInstance r) { super(r); }

    public void run() {
        super.run(); // note
        System.out.println("|Extend|");
    }
}

但这可能不是一个好主意,除非您真的知道自己在做什么。我们通常不应该改变 Thread.

的行为

另请参阅:

  • "implements Runnable" vs. "extends Thread"
  • What is the main advantage of extending Thread class (or when to extend Thread instead of implement runnable)
  • Defining and Starting a Thread

来自 Thread#start() 的 Javadocs:

Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.

因此,当您调用 start() 时,ThreadInstancerun 方法将被调用。

注意classThreaddefaultrun方法调用目标Runnablerun class:

// this is the run method of the base Thread class
public void run() {
    if (target != null) {
        target.run();
    }
}

但是因为你覆盖了子class中的run方法ThreadInstance,它不再调用目标RunnableInstance.

您已经覆盖了线程 class 的 run 方法并且您从未调用超级实现,因此永远不会调用 runnable。

您根本不需要覆盖线程,但如果必须,您应该在某个时候在 run 实现中调用 super.run()