扩展线程比实现 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 更可取的场景? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

扩展Thread类并实现Runnable接口的场景[重复]

Java多线程系列一——Java实现线程方法

Java核心技术-并发

线程实现Runnable接口比继承Thread的优势

MVC-ARS 是不是比经典 MVC 更可取以防止过载?

ThreadLocal 比 HttpServletRequest.setAttribute("key", "value") 更可取吗?