扩展Thread类的主要优势是什么(或者何时扩展Thread而不是实现Runnable接口)?

7
我正在尝试找出扩展Thread类的可能优势是什么?
这是另一个问题的一部分,我描述如下: 在Java中有两种创建线程的方式
1.继承Thread类 2.实现可运行接口
此处所述,使用可运行接口有几个好处。我的问题是从Thread类继承有什么优点?唯一想到的优点是可以从Thread类继承,并称其为ThreadExtended类。然后可以在ThreadExtended中添加更多功能(我不知道可能是什么),当想要创建一个线程时,可以从ThreadExtended而非Thread类进行扩展。
使用Thread类而非Runnable接口是否有任何优势?您是否知道任何从Thread类继承并要求用户从这些类继承以获得多线程功能的类?
    public class ThreadExtended extends Thread{
    //override some functions || add more functionality to Thread class
    }

    public class MyThread extends ThreadExtended{
     public void run()
    {
     for(int i=0;i<10;i++)
        {
          System.out.println("Using ThreadExtended instead of Thread directly");
        }
    }

    public static void main(String args[])
    {
    MyThread myThread = new MyThread();
    myThread.start();
    }
    }

1
在Java中只有一种创建线程的方式,那就是实例化一个Thread对象并调用它的start()方法。 - Sotirios Delimanolis
@SotiriosDelimanolis 我明白这一点,我在询问如何扩展而不是实例化。 - sheidaei
请注意我所提出的问题,它与您认为的重复问题略有不同。谢谢。 - sheidaei
那将会“启动”一个线程,没错。但扩展Thread类本身并不会启动线程。这是语义学问题! - Sotirios Delimanolis
肯定有至少一个令人信服的理由来扩展线程。实际上,没有一个答案真正回答了这个问题。 - Christopher Schneider
显示剩余2条评论
5个回答

9
很少有令人信服的理由来扩展Thread类。在大多数情况下,我想你最终会把所有的“做一些事情”的逻辑都放到run方法中。你应该坚持实现Runnable接口。选择扩展Thread类将创建一个可能毫无意义的类层次结构,并最终限制您在未来重构代码时的选项。选择实现Runnable接口不对实现者的血统做任何要求,您可以使用强大的抽象工具,如ExecutorService,以抽象掉运行代码的细节。最后,比起继承类,优先实现接口是一个好的实践!

5

只有当您需要添加与线程本身相关而非线程执行任务相关的行为时,才需要扩展Thread

例如,如果您正在实现一个线程池(由于存在java.util.concurrent,不建议再这么做),您需要更改线程的行为,使其能够(1)接受新工作和(2)将自己返回到池中。以非常简化的形式:

public void setRunnable(Runnable runnable) {
    this.runnable = runnable;
}

public void run() {
    while (true) {
        // wait on lock
        try {
            this.runnable.run();
        }
        catch (Throwable ex) {
            // do something with exception
        }
        finally {
            // return to pool
        }
    }
}

1
我发现如果我还配置线程,扩展线程会更加清晰,例如:
class FileReaper extends Thread {
    FileReaper() {
        setDaemon(true);
        setName(getClass().getSimpleName());
    }

    @Override public void run() {
        // do something
    }
}

0

如果你想创建一个 Looper 线程,扩展 Thread 也是一个很好的选择:

这是一个典型的 Looper 线程实现示例,使用 prepare() 和 loop() 的分离来创建一个初始的 Handler 与 Looper 进行通信。

  class LooperThread extends Thread {
      public Handler mHandler;

      public void run() {
          Looper.prepare();

          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          Looper.loop();
      }
  }

UI线程是一个Looper线程,但您可能希望创建自己的工作线程。要了解在Thread上运行其loop()方法的Looper的行为,请参见我的最新答案这里


0
简单来说,当您扩展Thread时,那将是您唯一扩展的类!

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