在什么情况下,扩展线程比实现Runnable接口更受欢迎?

11
作为一个初学者,我正在阅读有关Java多线程实现的两种方式。
我阅读了SO上和许多其他帖子上的这个thread
据说:
“喜欢Runnable”,仅当您正在特殊化线程行为时才扩展线程。
有人可以通过提供一小段片段来解释什么是专门化线程行为,帮助我理解这句话吗?

这只是以不同的方式表达了与其他回答相同的问题。 - Patrick
5个回答

12
您应该像扩展其他库类一样扩展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);
这就是扩展线程的用例。

2
这是一个非常好的答案。需要更多的赞。 - Chris Cudmore

2

专门化指的是扩展现有线程类的功能。根据应用程序的要求,它可以是任何东西。我下面提到的可能在逻辑上不正确。

public class MyThread extends Thread{
@Override
public void interrupt() {
    if(thread has started some operation on database){
        //roll back transaction
    }
    super.interrupt();
}
}

在中断线程之前,我们可以检查当前是否正在运行任何数据库操作并回滚它。虽然可以在中断的catch块中完成,但是如果您在应用程序的不同位置创建了大量此线程的实例,则从扩展类处理可以减少代码行数。这只是一个示例,没有人会以这种方式使用它。 :)

0

Java不支持多重继承,这意味着在Java中你只能扩展一个类,所以一旦你扩展了Thread类,你就失去了机会,不能再扩展或继承Java中的其他类,因此这个类专门用于线程。

通过扩展Thread,每个线程都有一个唯一的与之关联的对象,而实现Runnable,许多线程可以共享相同的可运行实例。

扩展一个类通常意味着添加新功能、修改或改进行为。如果我们没有对Thread进行任何修改,则使用Runnable接口即可。

当你想要对Thread进行一些修改时,可以将你的类与Thread类一起扩展并进行修改,因为Thread类的某些行为是由JDK开发人员决定的。


0

相比于Thread扩展,使用Runnable实现有几个优点:

  • 始终优先选择组合而不是继承,这样您最终将得到耦合度更低的代码。判断您的类与Thread之间的关系的一种方法是检查“is a”关系与“has a”关系。

  • 在实践中,扩展Thread将强制您为每个线程创建新的类实例,而不是在Runnable的情况下共享同一个实例。请参见this

  • Java仅支持单一继承

扩展Thread的合法用例之一是当您需要设计一个具有自定义属性(例如缓存资源)的Thread类,并且该类是CachedThreadPool的一部分时。


0
由于Java不支持多继承。 如果您有一个名为“Person”的类。
class Person{
 String name;
 int age;
}

那么你想创建一个类Man,它继承自Person

class Man extends Person{

}

现在你已经使用了extends关键字来声明Man是一个Person。那么如果你想让一个Man像一个线程一样运行,你不能再次继承Thread,因为Java不支持多重继承。所以只需使用Runnable接口,它可以与其他接口一起实现。

class Man extends Person implements Runnable{
  public void run()[
  }
}

编辑: “只有在专门化线程行为时才扩展线程”意味着您的类仅是一个没有其他功能的线程,因为当您的类包含其他功能时,您需要扩展其他超级类而不是Thread类。正如我之前提到的,Java不支持多重继承,因此只有在专门化线程行为时才扩展线程。


5
这并没有回答原帖提出的问题。 - Maroun
@Maroun,你能回答我的问题吗? - Raj
@Raj 我已经更新了我的答案,你可以看一下。 - tianwei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接