扩展线程比实现 Runnable 更可取的场景? [复制]
Posted
技术标签:
【中文标题】扩展线程比实现 Runnable 更可取的场景? [复制]【英文标题】:Scenario where extending thread is preferred than implement Runnable? [duplicate] 【发布时间】:2014-04-23 20:58:29 【问题描述】:作为一个初学者,我正在阅读关于在 Java 中实现多线程的 2 种方法。
我在 SO 和许多其他线程上阅读了这个 thread。
据说
"prefer runnable" ,仅当您专门针对线程的行为时才扩展线程。
谁能通过提供一小段帮助我理解这一行的 sn-p 来解释专门化 Thread 行为的含义。
【问题讨论】:
这只是与回答相同问题的其他问题不同。 【参考方案1】:选择 Runnable 实现而不是 Thread 扩展有几个原因:
总是更喜欢组合而不是继承,你最终会得到更少耦合的代码。 确定您的类如何与 Thread 相关的一种方法是检查“is a”关系与“has a”关系。
实际上,扩展 Thread 将强制您为每个线程创建类的新实例,而不是在 Runnable 的情况下共享同一个实例。见this。
Java 仅支持单继承
扩展 Thread 的一个合法用例示例是,当您需要设计一个具有自定义属性(例如:缓存资源)的 Thread 类时,该类属于 CachedThreadPool
【讨论】:
【参考方案2】:Java 不支持多重继承,这意味着你只能在 Java 中扩展一个类,所以一旦你扩展了 Thread
类,你就失去了机会,并且不能在 Java 中扩展或继承另一个类,所以这个类是专门为 Thread仅限。
通过extending Thread
,您的每个线程都有一个与之关联的唯一对象,而实现Runnable
,许多线程可以共享同一个可运行实例。
扩展类通常意味着添加新功能、修改或改进行为。如果我们不对Thread
进行任何修改,那么请改用Runnable
接口。
线程类有一些行为由 JDK 开发人员决定,当您想对其进行一些修改时,您可以使用 Thread
类扩展您的类并进行修改。
【讨论】:
【参考方案3】:因为java不支持多继承。 如果你有一个名为 Person 的类。
class Person
String name;
int age;
然后你想创建一个扩展 Person 的类 Man
class Man extends Person
现在您已经使用 extends 关键字声明 Man 是一个人。那么如果你想让Man
像线程一样执行,你不能再扩展Thread
,因为Java不支持多继承。所以只需使用Runnable
接口,它可以与其他接口一起实现。
class Man extends Person implements Runnable
public void run()[
编辑:
“仅当您专门研究线程的行为时才扩展线程”意味着您的类只是一个没有其他功能的线程,因为当您的类包含其他功能时,您需要扩展其他超类而不是 Thread
类。我之前提到过,java不支持多继承,所以只有在你专门研究线程的行为时才扩展线程。
【讨论】:
这不能回答 OP 的问题。 @Maroun 你能回答我的问题吗? @Raj 我已经更新了我的答案,你可以看看。【参考方案4】:您应该像扩展其他库类一样扩展Thread
。
以List
为例,更具体地说是ArrayList
,您可以在其上添加额外的行为,例如在添加某个谓词失败时拒绝某个值。
然后你可以称之为PredicatedArrayList
。
是否要在此处扩展 ArrayList
仍然是一个争论,但这个争论不适合这个问题。
因此,扩展线程的一个示例是在特定时间后杀死自己的线程。然后你会得到SuicidingThread extends Thread
,它可能需要一个构造函数来花时间。
这甚至强化了您应该将实际任务放在Runnable
中的论点。
比如Runnable somethingRunnable = new SomeClass();
,其中SomeClass implements Runnable
。
现在您可以执行以下任一操作:
Thread someThread = new Thread(somethingRunnable);
Thread someThread = new SuicidingThread(somethingRunnable, 5, TimeUnit.DAYS);
所以这将是一个扩展线程的用例。
【讨论】:
这是一个非常好的答案。需要更多的爱。【参考方案5】:专业化意味着,扩展现有线程类的功能。根据应用程序的要求,它可以是任何东西。我在下面提到的那个在逻辑上可能不正确。
public class MyThread extends Thread
@Override
public void interrupt()
if(thread has started some operation on database)
//roll back transaction
super.interrupt();
在这里,在中断线程之前,我们可以检查当前是否有任何数据库操作正在运行并回滚。虽然它可以从中断的 catch 块中完成,但如果您在应用程序的不同位置创建大量此线程的实例,则从扩展类处理它会减少行数。这只是一个例子,没有人会这样使用它。 :)
【讨论】:
以上是关于扩展线程比实现 Runnable 更可取的场景? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
ThreadLocal 比 HttpServletRequest.setAttribute("key", "value") 更可取吗?