从我在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

这两个代码块有什么显著的区别吗?


当前回答

我想说还有第三种方法:

public class Something {

    public void justAnotherMethod() { ... }

}

new Thread(new Runnable() {
   public void run() {
    instanceOfSomething.justAnotherMethod();
   }
}).start();

也许这受到了我最近大量使用Javascript和Actionscript 3的影响,但是这样你的类就不需要实现一个非常模糊的接口,比如Runnable。

其他回答

我不是专家,但我能想到实现Runnable而不是扩展Thread的一个原因:Java只支持单一继承,因此只能扩展一个类。

编辑:这原本是说“实现一个接口需要更少的资源”,但无论如何都需要创建一个新的线程实例,所以这是错误的。

有一件事我很惊讶,还没有提到,那就是实现Runnable使您的类更加灵活。

如果你扩展了线程,那么你正在做的动作总是在一个线程中。然而,如果你实现了Runnable,那就不必了。你可以在一个线程中运行它,或者将它传递给某种类型的执行器服务,或者将其作为一个任务在一个单线程应用程序中传递(可能稍后运行,但在同一个线程内)。如果只使用Runnable,则选项比将自己绑定到Thread时开放得多。

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]

我认为已经有很多关于这个话题的讨论,认为这可能对基础知识有所帮助。

可运行,因为:

为可运行的实现以扩展另一类将代码与处决允许您运行可从线程池运行事件线程,或以任何其他方式未来。

即使你现在不需要这些,你将来也可以。由于重写线程没有好处,Runnable是一个更好的解决方案。

最简单的解释是通过实现Runnable,我们可以将同一个对象分配给多个线程,并且每个线程共享相同的对象状态和行为。

例如,假设有两个线程,thread1在数组中放入一个整数,thread2在数组填满时从数组中取出整数。请注意,为了让thread2正常工作,它需要知道数组的状态,不管thread1是否已将其填满。

实现Runnable使您能够灵活地共享对象,而扩展Thread使您能够为每个线程创建新对象,因此thread1完成的任何更新都会丢失给thread2。