【问题标题】:What is the main advantage of extending Thread class (or when to extend Thread instead of implement runnable)扩展 Thread 类的主要优点是什么(或何时扩展 Thread 而不是实现可运行)
【发布时间】:2013-05-05 12:54:00
【问题描述】:

我试图找出扩展 Thread 类的可能优势是什么?

这是我描述的另一个问题的一部分: Java有两种创建线程的方式

  1. 从 Thread 类扩展
  2. 实现可运行接口

正如here 所解释的那样,使用可运行接口有几个好处。我的问题是从 Thread 类扩展有什么好处?我想到的唯一优点是可以从 Thread 类扩展,我们可以称之为 ThreadExtended 类。然后他/她可以在 ThreadExtended 中添加更多功能(我不知道那可能是什么),然后当他/她想创建一个线程时,而不是从 Thread 类扩展,它从 ThreadExtended 扩展。

使用 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();
    }
    }

【问题讨论】:

  • 在java中创建线程只有一种方法,那就是实例化Thread并在其上调用start()
  • @SotiriosDelimanolis 我明白,我问的是扩展而不是实例化
  • 请注意我提出的问题,它与您认为它重复的问题略有不同。谢谢
  • 扩展类不会创建线程。
  • @SotiriosDelimanolis 我从 ThreadExtended 扩展而来,它从 Thread 类扩展而来,所以我在那个类上调用 start,不是吗?

标签: java multithreading


【解决方案1】:

很少有令人信服的理由来扩展 Thread 类。我想在大多数情况下,无论如何,您最终都会将所有“做一些事情”逻辑扔到 run 方法中。

您绝对应该坚持实施 Runnable。通过选择扩展 Thread,您正在创建一个可能是荒谬的类层次结构,并且最终会限制您将来重构事物的选择。通过选择实现 Runnable,您无需对实现者的血统提出任何要求,并且您可以使用像 ExecutorService 这样的强大抽象来抽象出运行一大块代码的具体细节。最后,宁愿实现接口而不是扩展类是一个好习惯!

【讨论】:

    【解决方案2】:

    扩展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
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果我还配置线程,我发现扩展 Thread 会更清晰,例如:

      class FileReaper extends Thread {
          FileReaper() {
              setDaemon(true);
              setName(getClass().getSimpleName());
          }
      
          @Override public void run() {
              // do something
          }
      }
      

      【讨论】:

        【解决方案4】:

        简单地说,当您扩展 Thread 时,它将是您将要扩展的唯一类!

        【讨论】:

          【解决方案5】:

          还有一个很好的理由来扩展Thread - 如果你想创建一个 Looper 线程:

          这是一个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 线程,但您可能想要创建自己的工作 Looper 线程。要了解带有 LooperThread 在其上运行 loop() 方法的行为方式,请参阅我最近的回答 here

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-06-02
            • 1970-01-01
            • 2011-02-16
            • 2011-01-22
            • 2013-01-23
            • 1970-01-01
            • 2018-01-10
            • 2016-11-09
            相关资源
            最近更新 更多