我阅读了SO上和许多其他帖子上的这个thread。
据说:
“喜欢Runnable”,仅当您正在特殊化线程行为时才扩展线程。
有人可以通过提供一小段片段来解释什么是专门化线程行为,帮助我理解这句话吗?
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);
专门化指的是扩展现有线程类的功能。根据应用程序的要求,它可以是任何东西。我下面提到的可能在逻辑上不正确。
public class MyThread extends Thread{
@Override
public void interrupt() {
if(thread has started some operation on database){
//roll back transaction
}
super.interrupt();
}
}
Java不支持多重继承,这意味着在Java中你只能扩展一个类,所以一旦你扩展了Thread
类,你就失去了机会,不能再扩展或继承Java中的其他类,因此这个类专门用于线程。
通过扩展Thread
,每个线程都有一个唯一的与之关联的对象,而实现Runnable
,许多线程可以共享相同的可运行实例。
扩展一个类通常意味着添加新功能、修改或改进行为。如果我们没有对Thread
进行任何修改,则使用Runnable
接口即可。
当你想要对Thread
进行一些修改时,可以将你的类与Thread
类一起扩展并进行修改,因为Thread
类的某些行为是由JDK开发人员决定的。
相比于Thread扩展,使用Runnable实现有几个优点:
始终优先选择组合而不是继承,这样您最终将得到耦合度更低的代码。判断您的类与Thread之间的关系的一种方法是检查“is a”关系与“has a”关系。
在实践中,扩展Thread将强制您为每个线程创建新的类实例,而不是在Runnable的情况下共享同一个实例。请参见this。
Java仅支持单一继承
扩展Thread的合法用例之一是当您需要设计一个具有自定义属性(例如缓存资源)的Thread类,并且该类是CachedThreadPool的一部分时。
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不支持多重继承,因此只有在专门化线程行为时才扩展线程。