【发布时间】:2011-07-23 16:05:21
【问题描述】:
当我们可以通过实现 Runnable 并将其传递给 Thread 构造函数来实现相同的功能时,允许用户通过扩展 Thread 类来创建线程的本质是什么。
【问题讨论】:
标签: java multithreading language-design runnable library-design
当我们可以通过实现 Runnable 并将其传递给 Thread 构造函数来实现相同的功能时,允许用户通过扩展 Thread 类来创建线程的本质是什么。
【问题讨论】:
标签: java multithreading language-design runnable library-design
通过以下方式实现相同的功能 实现 Runnable 并将其传递给 线程构造函数
扩展Thread的使用不限于Runnable。例如,您可以change the behavior of some methods 或添加您自己的线程本地信息(始终使用Thread.currentThread() 访问)。
【讨论】:
从历史的角度来看,您需要了解Thread API 是在 Java 1.0 中设计的,在 Java 支持匿名内部类之前。很多早期的示例代码都显示了Thread 的子类化。直到后来:
Runnable 实例说 “.Net 中的 Thread 类被标记为 final”是很好的说法,但你必须意识到 C# / .Net 在几年后出现......并且是能够学习Java的设计。 Java 曾经/现在被许多不太完美的设计决策的历史包袱所困……因为不破坏旧代码的压倒一切的必要性。
【讨论】:
Thread 的不寻常之处在于它可以引用Runnable 来运行,但它本身也是Runnable。默认情况下,Thread 将使用自己作为 Runnable 实例来运行,当然你可以将它指向其他地方。
我认为没有充分的理由将Thread 标记为最终并需要外部Runnable 或使Thread 可扩展并使其成为自己的Runnable。两种方法都非常好,似乎没有一种比另一种更好。
如果我不得不猜测,使Thread 成为子类的原因是它允许您编写这样的代码:
Thread t = new Thread() {
public void run() {
/* ... your code here ... */
}
};
这比创建Runnable 的子类然后将其包装在线程中要干净一些。同样,您可以从Thread 继承子类以获得Runnable,该Runnable 清楚地表明它应该用作线程。当然,这主要是一个美学问题,如果 Java 设计者采取相反的方式,我认为这将是一个非常好的决定。
【讨论】:
Thread.isCCLOverridden(Class)
如果我可以添加一些东西,通过扩展 Thread,您可以拥有线程的扩展功能(Runnable 中不存在,因为它只包含 run() 方法),比如允许您的线程充当守护线程(就像垃圾收集器守护线程)。其他线程存在,例如调用类的 main 方法的单个非守护线程(当 JVM 启动时)。
Runnable 接口允许您的类作为线程激活(通过实现run() 方法)。
【讨论】:
线程类描述线程如何运行,Runnable 描述运行什么。如果要修改运行的内容,则应实现 Runnable。如果你想修改线程的运行方式,你可以从 Thread 派生。如果您想修改线程的运行方式,您可以从 Thread 派生并实现一个单独的 Runnable 对象。
【讨论】:
我能想到的唯一好处是:如果你扩展 Thread 类,它会让你的 run() 方法被标记为受保护。 实现 Runnable 的一个缺点是您的 run 方法必须标记为公共。
【讨论】: