Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么java中的java.lang.Thread类没有被设计者标记为final?_Java_Multithreading_Language Design_Runnable_Library Design - Fatal编程技术网

为什么java中的java.lang.Thread类没有被设计者标记为final?

为什么java中的java.lang.Thread类没有被设计者标记为final?,java,multithreading,language-design,runnable,library-design,Java,Multithreading,Language Design,Runnable,Library Design,当我们可以通过实现Runnable来实现相同的功能并将其传递给线程构造函数时,允许用户通过扩展thread类来创建线程的本质是什么。thread是不寻常的,因为它可以引用Runnable来运行,但它本身也是可运行的。默认情况下,线程将使用自身作为要运行的可运行实例,当然您可以将其指向其他地方 我认为这不是一个很好的理由来标记Threadfinal并要求一个外部Runnable,或者使Thread可扩展并使其成为自己的Runnable。这两种方法都非常好,而且两种方法都不是比另一种更好的选择 如果

当我们可以通过实现Runnable来实现相同的功能并将其传递给线程构造函数时,允许用户通过扩展thread类来创建线程的本质是什么。

thread
是不寻常的,因为它可以引用
Runnable
来运行,但它本身也是可运行的。默认情况下,
线程
将使用自身作为要运行的
可运行
实例,当然您可以将其指向其他地方

我认为这不是一个很好的理由来标记
Thread
final并要求一个外部
Runnable
,或者使
Thread
可扩展并使其成为自己的
Runnable
。这两种方法都非常好,而且两种方法都不是比另一种更好的选择

如果我不得不猜测的话,将
线程
子类化的原因是它允许您编写如下代码:

Thread t = new Thread() {
    public void run() {
       /* ... your code here ... */
    }
};
这比创建
Runnable
的子类,然后将其包装到线程中稍微干净一些。类似地,您可以对
线程
进行子类化,以获得一个
可运行的
,它清楚地表明它应该用作线程。当然,这主要是一个美学问题,如果Java设计人员采取相反的做法,我认为这将是一个完美的决定

通过以下方式实现相同的功能: 实现Runnable并将其传递给 线程构造函数


扩展线程的使用不限于Runnable。例如,您可以添加或添加自己的线程本地信息(总是可以通过
thread.currentThread()
访问)。

如果我可以添加一些内容,通过扩展
thread
您可以拥有线程的扩展功能(该功能在
Runnable
中不存在,因为它只包含
run()
方法)比如允许线程充当守护进程线程(就像垃圾收集器守护进程线程一样)。其他线程的存在类似于单个非守护进程线程,该线程调用类的主方法(当JVM启动时)


Runnable
接口允许类作为线程激活(通过实现
run()
方法)。

从历史的角度来看,您需要了解
thread
API是在Java支持匿名内部类之前,在Java 1.0中设计的。许多早期的示例代码显示了
线程的子类化。直到后来:

  • 他们增加了对匿名内部类的支持(Java1.1)
  • 他们发现最好使用内部类(etc)来提供
    Runnable
    实例
  • 他们实现了用于任务执行、线程池等的标准类(Java5.0)

说“.Net中的线程类被标记为final”是很好的,但您必须意识到C#/.Net是在若干年后出现的。。。并且能够从Java的设计中学习。Java曾经/正在被一些不太完美的设计决策的历史包袱所困扰。。。因为一个最重要的命令是不要破坏旧代码。

thread类描述线程如何运行,Runnable描述运行的内容。如果要修改正在运行的内容,应该实现Runnable。如果要修改线程的运行方式,请从线程派生。在需要修改线程运行方式的情况下,可以从线程派生并实现一个单独的可运行对象

我能想到的唯一一件好事是:如果扩展Thread类,它会让run()方法被标记为受保护。实现Runnable的一个缺点是你的run方法必须被标记为public。

它在语法上更干净,但在设计上不干净,并且在卸载当前类加载器(例如在app server中)时可能会产生残酷的影响(perm gen leak)。@Piotr、类垃圾和所有静态jazz,不幸的是,仅仅不重写线程并不能解决这个问题,即使在死线程上,CCL也是作为引用保留的,这本身就可能造成足够的伤害。inheritedAccessControlContext和runnable保留在正在运行的线程上,因此imo.overriding线程有一些含义,比如跟踪危险的线程子类(例如override get/setContextClassLoader()),这会导致一些额外的操作和同步<代码>线程.iscloverridden(类)