当前位置: 首页 > 知识库问答 >
问题:

为什么线程要实现Runnable?

公良理
2023-03-14

Java线程的run()方法在线程启动时由该线程上的JVM调用。要让线程做一些事情,您可以创建thread的子类并重写它的run()方法,或者(最好)您可以为线程的构造函数提供一个Runnable。那很好。

当时我正在创建Thread的子类并重写run,我意识到我不能像预期的那样使方法受到保护,因为Thread.run()是公共的。然后我意识到为什么:它必须是公共的,因为Thread实现了Runnable。但它为什么要实现Runnable呢?

这似乎不合逻辑。一个线程是可启动的(从当前线程),但您不以运行()一个Runnable(从当前线程)的方式运行它;线程运行自己(在自己的线程上)。如果您手动调用线程的run方法,那么您就不是将它用作线程,而是一个重量级的Runnable。

由于设计的原因,任何可以访问Thread对象的代码都可以调用它的public run方法,并潜在地插入不打算是public的或设计为这样调用的代码。它还允许像这样非常奇特的事情:

Thread.currentThread.run();

线程实现Runnable的合法用途是我没有看到的吗?

共有1个答案

屈俊远
2023-03-14

原因是“向下兼容”。

thread类起源于Java1.0...或更早版本。在那个年代,Java没有内部类,因此没有实现runnable实例的轻量级方法。如果您查看那个时代的旧线程示例和教程,通常会看到扩展thread并重写run()方法的类。

随着时间的推移,人们意识到扩展thread不是一个好主意(出于各种原因)。但是,thread设计无法更改,因为这会使旧的Java代码与较新的JVM不兼容。

在某些情况下,扩展线程并重写run()方法是有意义的。例如,您可能希望run()实现某种特殊的机制,用于将信息传入或传出提供的runnable中,或者实现某种特殊的异常处理,或者...使线程“可重新启动”。

甚至可能有这样的情况:您希望直接在线程对象上调用run()。例如,如果给您一些扩展thread的“狗早餐”代码,您必须将其转换为在线程池中运行,而不修改原始代码。您可能会考虑实例化crufty thread类,并将实例作为Runnable传递给threadpool以运行。(是的……惨不忍睹!)

 类似资料:
  • 本文向大家介绍为什么要用线程池? 相关面试题,主要包含被问及为什么要用线程池? 时的应答技巧和注意事项,需要的朋友参考一下 池化技术相比大家已经屡见不鲜了,线程池、数据库连接池、Http 连接池等等都是对这个思想的应用。池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。** 线程池提供了一种限制和管理资源(包括执行一个任务)。 每个线程池还维护一些基本统计信息,例如已完成任务的数

  • 我没有受过CS方面的教育,但我已经专业地用Java编程近十年了,我从未见过任何人在生产系统中实现。这并不意味着它没有它的用途,或者和我一起工作的人一直在做正确的事情。 所以我的问题是,有哪些实现的用例不能通过语言中的另一个进程或语法更可靠地处理? 请提供具体的场景或您的经验,简单地重复一本Java教科书,或者Finalize的预期用途是不够的,因为这不是本问题的意图。

  • 本文向大家介绍为什么要使用多线程?相关面试题,主要包含被问及为什么要使用多线程?时的应答技巧和注意事项,需要的朋友参考一下 先从总体上来说: 从计算机底层来说:线程可以比作是轻量级的进程,是程序执行的最小单位,线程间的切换和调度的成本远远小于进程。另外,多核 CPU 时代意味着多个线程可以同时运行,这减少了线程上下文切换的开销。 从当代互联网发展趋势来说:现在的系统动不动就要求百万级甚至千万级的并

  • 问题内容: 我已经阅读了许多关于Java的新手问题,发现令人困惑的是,没有人真的说过是清理资源的不可靠方法。我看到有人评论说他们用它来清理,这确实很吓人,因为要保证关闭的唯一方法就是最终实现。 我没有在CS上学,但是近十年来我一直在用Java专业编程,而且从未见过有人在生产系统中实现过。这仍然并不意味着它没有用途,或者与我一起工作的人都在正确地做它。 所以我的问题是,存在哪些用例无法通过语言中的其

  • 我被这个概念困住了。 这是我在一个站点上看到的解释的一部分: 隐藏实现 我是这样想象的: 库客户机是否知道这个实现有什么区别?

  • 使用ScalaTest 3.0.0环境:Scala 2.11.8、sbt 0.13.5、IntelliJ 14.1.4 建筑sbt只有 以下测试通过。然而,IntelliJ在MyMiniTest下方标记了一条弯曲的红线,并显示警告信息: 类“MyMiniTest”必须声明为抽象的,或实现抽象成员“convertToLegacyEqualizer[T](左:T):TripleEqualSupport