从我在Java中使用线程的时间来看,我发现了两种编写线程的方法:
使用可运行的机具:
public class MyRunnable implements Runnable {
public void run() {
//Code
}
}
//Started with a "new Thread(new MyRunnable()).start()" call
或者,使用扩展线程:
public class MyThread extends Thread {
public MyThread() {
super("MyThread");
}
public void run() {
//Code
}
}
//Started with a "new MyThread().start()" call
这两个代码块有什么显著的区别吗?
随着Java8的发布,现在有了第三个选项。
Runnable是一个函数接口,这意味着可以使用lambda表达式或方法引用创建它的实例。
您的示例可以替换为:
new Thread(() -> { /* Code here */ }).start()
或者如果要使用ExecutorService和方法引用:
executor.execute(runner::run)
这些不仅比示例要短得多,而且还具有其他答案中所述的使用Runnable over Thread的许多优点,例如单一责任和使用组合,因为您没有专门处理线程的行为。如果您只需要一个Runnable,那么这种方法也可以避免创建一个额外的类。
如果您希望实现或扩展任何其他类,那么Runnable接口是最可取的,否则,如果您不希望任何其他类扩展或实现,那么Thread类是最好的。
最常见的区别是
当您扩展Thread类时,在此之后,您不能扩展所需的任何其他类。(如您所知,Java不允许继承多个类)。
当您实现Runnable时,您可以为您的类节省空间,以便将来或现在扩展任何其他类。
Java不支持多个继承,这意味着您只能在Java中扩展一个类,因此一旦扩展了Thread类,您就失去了机会,无法在Java中延伸或继承另一个类。在面向对象编程中,扩展类通常意味着添加新功能,以及修改或改进行为。如果我们没有对线程进行任何修改,那么请改用Runnable接口。可运行接口表示一个任务,它可以由普通线程或执行器或任何其他方式执行。因此,将Task逻辑分离为Runnable而不是Thread是一个很好的设计决策。将任务分离为可运行任务意味着我们可以重用任务,也可以通过不同的方式执行任务。因为一旦线程完成,就不能重新启动它。任务的Runnable与Thread,Runnable是赢家。Java设计器认识到这一点,这就是为什么Executors接受Runnable作为Task,并且他们有执行这些任务的工作线程。继承所有线程方法只是表示一个任务的额外开销,这可以通过Runnable轻松完成。
由javareviewed.blogspot.com提供
这是Java中Thread和Runnable之间的一些显著差异。如果您知道Thread与Runnable之间的其他差异,请通过评论分享。我个人在这个场景中使用Runnable over Thread,并建议根据您的需求使用Runnable或Callable接口。
然而,显著的区别是。
当您扩展Thread类时,每个线程都会创建一个唯一的对象并与其关联。当您实现Runnable时,它将同一对象共享给多个线程。
1.扩展线程接口,就像让类只作为线程一样。您的新类将像一个增强的线程。
jshell> public class Test extends Thread{
...> public Test(String name){
...> super(name);
...> }
...> public void run(){
...> System.out.println(Thread.currentThread().getName());
...> }
...> }
| created class Test
jshell> Test t1=new Test("MyThread");
t1 ==> Thread[MyThread,5,main]
它创建一个线程,而不是Test对象。所以它会像一个线程。不能在线程之间共享Test类的实例。
2.实现可运行接口。
jshell> public class Test1 implements Runnable{
...> public void run(){
...> System.out.println(Thread.currentThread().getName());
...> }
...> public String getName(){
...> return "testing";}
...> }
| created class Test1
jshell> Test1 t1=new Test1();
t1 ==> Test1@396a51ab --> this creates Test1 object.
该对象可以通过以下方式跨线程共享,
jshell> Thread t1=new Thread(t1,"Hai");
t ==> Thread[Hai,5,main]
jshell> Thread t=new Thread(t1,"Hai");
t ==> Thread[Hai,5,main]
我认为已经有很多关于这个话题的讨论,认为这可能对基础知识有所帮助。