为什么Java中的java.lang.Thread类没有被设计者标记为final?
当我们可以通过实现 Runnable 并将其传递给 Thread 构造函数来实现相同的功能时,允许用户通过扩展 Thread 类来创建线程的本质是什么。
What is the essence of allowing the user to create thread by extending the Thread class when we can achieve the same functionality by implementing Runnable and pass it to the Thread constructor.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
扩展Thread 的用途不限于Runnable。例如,您可以更改某些方法的行为或添加您自己的本地线程信息(始终可以通过 Thread.currentThread() 访问)。
The use of extending Thread is not limited to Runnable. For example you can change the behavior of some methods or add your own thread local information (always accessible with
Thread.currentThread()
).从历史的角度来看,您需要了解
Thread
API 是在 Java 1.0 中设计的,早于 Java 支持匿名内部类。许多早期的示例代码都显示了Thread
的子类化。直到后来:“.Net 中的 Thread 类被标记为 Final”这句话很好,但您必须意识到 C# / .Net 是在几年后出现的……并且能够学习从Java的设计开始。 Java 过去/现在都背负着许多不太完美的设计决策的历史包袱……因为不破坏旧代码是压倒一切的要求。
From a historical perspective, you need to understand that the
Thread
API was designed in Java 1.0, before Java supported anonymous inner classes. And a lot of the early example code shows subclassing ofThread
. It wasn't until later that:Runnable
instancesIt is all very well saying "the Thread class in .Net is marked final", but you have to realize that C# / .Net came along a number of years later ... and was able to learn from the design of Java. Java was / is stuck with the historical baggage of a number of less-than-perfect design decisions ... because of an overriding imperative to NOT break old code.
Thread
的不同寻常之处在于,它可以引用对Runnable
的引用来运行,但它本身也是Runnable
。默认情况下,Thread
将使用自身作为Runnable
实例来运行,当然您也可以将其指向其他位置。我认为没有充分的理由将
Thread
标记为 Final 并需要外部Runnable
或使Thread
可扩展并让它成为自己的<代码>可运行。这两种方法都非常好,而且似乎没有一种比另一种更好。如果我不得不猜测,使
Thread
可子类化的原因是它允许您编写如下代码:这比创建
Runnable
的子类然后包装要干净得多它在一个线程中。同样,您可以从Thread
派生子类以获得一个Runnable
,它清楚地表明它应该用作线程。当然,这主要是一个美观问题,如果 Java 设计者采取相反的方式,我认为这将是一个非常好的决定。Thread
is unusual in that it can take a reference to theRunnable
to run, but it itself is alsoRunnable
. By default, theThread
will use itself as theRunnable
instance to run, though of course you can point it someplace else.I think that that's no good reason to either mark
Thread
final and require an externalRunnable
or to makeThread
extendible and have it be its ownRunnable
. Both approaches are perfectly fine and neither one seems like a much better choice than the other.If I had to guess, the reason for making
Thread
subclassable is that it allows you to write code like this:Which is marginally cleaner than creating a subclass of
Runnable
and then wrapping it in a thread. Similarly, you can subclass off ofThread
to get aRunnable
that clearly indicates that it's supposed to be used as a thread. Of course, this is mostly a question of aesthetics, and had the Java designers gone the other way with this I think it would have been a perfectly fine decision.如果我可以添加一些东西,通过扩展 Thread ,您可以拥有线程的扩展功能(这在 Runnable 中不存在,因为它只包含 run( ) 方法),就像允许您的线程充当守护线程(就像垃圾收集器守护线程一样)。其他线程的存在类似于单个非守护线程,它调用类的 main 方法(当 JVM 启动时)。
Runnable 接口允许您的类作为线程激活(通过实现 run() 方法)。
If I acan add something, by extending
Thread
you can have extended functionality of a thread (which is doesn't exist inRunnable
as it only contains therun()
method) like allowing your thread to act as a daemon thread (just like the Garbage Collector Daemon Thread). Other threads exists like the single non-daemon thread which calls the main method of a class (when the JVM starts up).The
Runnable
interface allows your class to become active as thread (by implementing arun()
method).线程类描述了线程如何运行,Runnable 描述了运行什么。如果你想修改运行的内容,你应该实现 Runnable。如果您想修改线程的运行方式,您可以从 Thread 派生。如果您想要修改线程的运行方式,您可以从 Thread 派生并实现一个单独的 Runnable 对象。
The thread class describes how the thread runs, the Runnable describes what is run. If you want to modify what is run, you should implement Runnable. If you want to modify how the thread is run you derive from Thread. In the case where you want to modify how a thread is run, you may derive from Thread and implement a separate Runnable object.
我能想到的唯一好的事情是:如果您扩展 Thread 类,它可以让您的 run() 方法被标记为受保护。实现 Runnable 的一个缺点是您的运行方法必须标记为公共。
The only good thing I can think of is: if you extend the Thread class, It lets your run() method to be marked as protected. One disadvantage of implementing Runnable is that your run method MUST be marked as public.