【问题标题】:Java: Parameterized RunnableJava:参数化可运行
【发布时间】:2010-12-12 05:05:36
【问题描述】:

标准Runnable 接口只有非参数化run() 方法。还有Callable<V> 接口与call() 方法返回泛型类型的结果。我需要传递通用参数,如下所示:

interface MyRunnable<E> {
  public abstract void run(E reference);
}
为此目的是否有任何标准接口,或者我必须自己声明那个基本接口?

【问题讨论】:

  • 如果您在使用 匿名内部 RunnableCallable&lt;V&gt; 时遇到此问题,则您不能也不需要使用参数。请参阅 this questionthe answer 如何做到这一点。

标签: java generics callable


【解决方案1】:

通常您会将RunnableCallable 实现为支持通用输入参数的类;例如

public class MyRunnable<T> implements Runnable {
  private final T t;

  public MyRunnable(T t) {
    this.t = t;
  }

  public void run() {
    // Reference t.
  }
}

【讨论】:

  • 感谢所有三个回答我问题的人,他们都给出了相同的正确答案。应该接受所有三个答案... :)
  • 是的 :) 你是对的。我应该等待几个小时才能逐渐消失。
【解决方案2】:

通常,如果您想将参数传递给run() 方法,您将使用带有参数的构造函数子类化Runnable

例如,你想这样做:

// code
Runnable r = new YourRunnable();
r.run(someParam);
//more code

你需要这样做:

// code
Runnable r = new YourRunnable(someParam);
r.run();
//more code

您将实现YourRunnable,类似于以下内容:

public class YourRunnable implements Runnable {
    Some param;
    public YourRunnable(Some param){
        this.param = param;
    }
    public void run(){
        // do something with param
    }
}

【讨论】:

    【解决方案3】:

    Runnable 并不意味着由客户端代码直接调用,例如 foo.run(),它将在当前线程中按顺序运行。

    来自Runnable API

    Runnable 接口应该是 由任何类实现 实例旨在执行 由一个线程。该类必须定义一个 没有参数的方法称为 run。

    此接口旨在提供 对象的通用协议 希望在它们运行时执行代码 积极的。例如,Runnable 是 由类 Thread 实现。存在 活动只是意味着一个线程有 已开始但尚未开始 停止了。

    此外,Runnable 提供 意味着一个类是活跃的,而 不是子类化线程。一个类 实现 Runnable 可以在没有的情况下运行 通过实例化 Thread 子类化 线程实例并传入 作为目标。在大多数情况下, 应使用可运行接口,如果 您只打算覆盖 run() 方法,没有其他线程 方法。这很重要,因为 类不应该被子类化 除非程序员打算 修改或增强基本 类的行为。

    相反,您基于您的可运行对象创建一个新的 Thread 实例,然后调用 bar.start()。然后 JVM 负责在这个单独的线程中调用 run()

    例子:

     public class Foo<E> implements Runnable {
         private final E e;
         public Foo(E e) { ... }
         @Override
         public void run() {
             do something with e.
         }
     }
    
     Foo<String> foo = new Foo("hello");
     Thread bar = new Thread(foo);
     bar.start();
    

    【讨论】:

    • Runnable 在显式线程之外还有很多用途。接口的语义只是“一个对象,代表在某个时间运行的一项工作”。
    • 不同意您的评论。请参阅 API 了解其预期用途。
    • 我同意古斯塔夫的观点。如果多线程是 Runnable 的唯一预期用途,那么它将在 java.util.concurrent 中定义,而不是在 java.lang 中。但更重要的是,您关于“Runnable 不应该由客户端代码直接调用”的说法是不正确的——如果是这种情况,文档不会建议实例化线程并将自身传递给 run() 的实现. 在那个用例中,如果您不直接调用run(),并且不依赖 Executor 来处理线程(Runnable 正在处理线程本身),它是如何运行的?简单 - 只需致电 run()
    • @Dathan Runnable 不在 java.util.concurrent 中,因为前者起源于 Java 1,而后者在几年后出现在 Java 5 中。
    【解决方案4】:

    我建议按照原始问题中的方式定义一个界面。此外,通过使接口特定于它应该做的事情来避免弱类型,而不是像Runnable 这样的无意义接口。

    【讨论】:

      【解决方案5】:

      还有来自Google Collections@987654321@Guava

      如果您将输出类型设置为?Void(并始终返回null),您可以使用它作为Runnable 的替代输入参数。

      这样做的好处是能够使用Functions.compose 转换输入值,Iterables.transform 将其应用于集合的每个元素等。

      【讨论】:

        【解决方案6】:

        Java 8 包含 java.util.function.Consumer&lt;T&gt; 接口和单个非默认方法 void accept(T t)

        还有很多其他相关的接口in that package

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-01-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-27
          • 2020-05-05
          • 1970-01-01
          相关资源
          最近更新 更多