【问题标题】:Scenario where extending thread is preferred than implement Runnable? [duplicate]扩展线程比实现 Runnable 更可取的场景? [复制]
【发布时间】:2014-04-23 20:58:29
【问题描述】:

作为一个初学者,我正在阅读关于在 Java 中实现多线程的 2 种方法。

我在 SO 和许多其他线程上阅读了这个 thread

据说

"prefer runnable" ,仅当您专门针对线程的行为时才扩展线程。

谁能通过提供一小段帮助我理解这一行的 sn-p 来解释专门化 Thread 行为的含义。

【问题讨论】:

  • 这只是与回答相同问题的其他问题不同。

标签: java multithreading runnable


【解决方案1】:

选择 Runnable 实现而不是 Thread 扩展有几个原因:

  • 总是更喜欢组合而不是继承,你最终会得到更少耦合的代码。 确定您的类如何与 Thread 相关的一种方法是检查“is a”关系与“has a”关系。

  • 实际上,扩展 Thread 将强制您为每个线程创建类的新实例,而不是在 Runnable 的情况下共享同一个实例。见this

  • Java 仅支持单继承

扩展 Thread 的一个合法用例示例是,当您需要设计一个具有自定义属性(例如:缓存资源)的 Thread 类时,该类属于 CachedThreadPool

【讨论】:

    【解决方案2】:

    Java 不支持多重继承,这意味着你只能在 Java 中扩展一个类,所以一旦你扩展了 Thread 类,你就失去了机会,并且不能在 Java 中扩展或继承另一个类,所以这个类是专门为 Thread仅限。

    通过extending Thread,您的每个线程都有一个与之关联的唯一对象,而实现Runnable,许多线程可以共享同一个可运行实例。

    扩展类通常意味着添加新功能、修改或改进行为。如果我们不对Thread 进行任何修改,那么请改用Runnable 接口。

    线程类有一些行为由 JDK 开发人员决定,当您想对其进行一些修改时,您可以使用 Thread 类扩展您的类并进行修改。

    【讨论】:

      【解决方案3】:

      因为java不支持多继承。 如果你有一个名为 Person 的类。

      class Person{
       String name;
       int age;
      }
      

      然后你想创建一个扩展 Person 的类 Man

      class Man extends Person{
      
      }
      

      现在您已经使用 extends 关键字声明 Man 是一个人。那么如果你想让Man像线程一样执行,你不能再扩展Thread,因为Java不支持多继承。所以只需使用Runnable接口,它可以与其他接口一起实现。

      class Man extends Person implements Runnable{
        public void run()[
        }
      }
      

      编辑: “仅当您专门研究线程的行为时才扩展线程”意味着您的类只是一个没有其他功能的线程,因为当您的类包含其他功能时,您需要扩展其他超类而不是 Thread 类。我之前提到过,java不支持多继承,所以只有在你专门研究线程的行为时才扩展线程。

      【讨论】:

      • 这不能回答 OP 的问题。
      • @Maroun 你能回答我的问题吗?
      • @Raj 我已经更新了我的答案,你可以看看。
      【解决方案4】:

      您应该像扩展其他库类一样扩展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);

      所以这将是一个扩展线程的用例。

      【讨论】:

      • 这是一个非常好的答案。需要更多的爱。
      【解决方案5】:

      专业化意味着,扩展现有线程类的功能。根据应用程序的要求,它可以是任何东西。我在下面提到的那个在逻辑上可能不正确。

      public class MyThread extends Thread{
      @Override
      public void interrupt() {
          if(thread has started some operation on database){
              //roll back transaction
          }
          super.interrupt();
      }
      }
      

      在这里,在中断线程之前,我们可以检查当前是否有任何数据库操作正在运行并回滚。虽然它可以从中断的 catch 块中完成,但如果您在应用程序的不同位置创建大量此线程的实例,则从扩展类处理它会减少行数。这只是一个例子,没有人会这样使用它。 :)

      【讨论】:

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