【问题标题】:Where to use callable and where to use Runnable Interface?在哪里使用 callable 以及在哪里使用 Runnable Interface?
【发布时间】:2016-09-24 07:56:33
【问题描述】:

我对 Java 还很陌生,我正在研究多线程的概念,在经历使用多线程的各种实现时,我经历了这两个概念。 这个The difference between the Runnable and Callable interfaces in Java 问题说明了两者之间有什么区别以及在哪里使用。

我怀疑 Callable 是否能够做 Runnable 的所有事情,为什么这么多人使用 Runnable 而不是 callable? 与 Runnable 接口相比,实现 Callable 接口是否有额外的开销?

【问题讨论】:

  • 如果你不需要它,你不应该使用 Callable。正如KISS principle 所说。

标签: java runnable callable


【解决方案1】:

为什么这么多人使用 Runnable 而不是 callable?

Callable 是 jdk 中极具竞争力的新功能,它附带了 Executor 框架,为线程执行提供了更大的灵活性。

在实现 Callable 接口时是否有任何额外的开销 与可运行接口比较?

我不这么认为,如果您遵循任何标准的 Executor 文档,这将非常简单。

【讨论】:

    【解决方案2】:

    一个重要的区别:Runnable接口中的run()方法返回void; Callable 接口中的call() 方法返回T 类型的对象。这使您可以轻松访问响应对象。

    您可以通过创建私有数据成员并提供 getter 来对 Runnable 的具体实现做同样的事情,但语法糖很甜。

    【讨论】:

      【解决方案3】:

      java.util.concurrent 包出现在Java 5 版本之前,实际上没有其他选择可以进行并发计算,只能直接操作Threads。

      您可以直接操作线程,例如通过子类化:

      public class MyThread extends Thread {
          public void run() {
              myComputation();
          }
      }
      

      或者您可以通过创建Runnable 来做同样的事情,这是首选方式(主要是因为您不需要子类化任何东西,这提供了清晰的关注点分离、更好的代码重用或通常更好的组合) :

      public class MyRunnable implements Runnable {
          public void run() {
              mycomputation();
          }
      }
      new Thread(new MyRunnable()).start();
      

      但无论您使用哪种方式,您都必须创建、启动、操作、加入线程。哪个有缺点:您可以创建多少个线程?这个贵吗? (在某些时候确实如此,尽管随着每个 JVM 实现它变得越来越便宜。)

      另外,这个 API 本身有一些开发人员必须克服的限制:如果我想从 Runnable 返回一个值,但看到签名仍然不允许呢?我如何知道我的Runnable 是否因Exception 而失败?诸如异常处理程序之类的东西可以通过线程来实现,但这是一个重复的、容易出错的任务。

      进入java.util.concurrent 包!它为所有这些(以及更多)提供了答案!

      您希望将线程重用于多个“工作单元”(是否是Runnable?):您可以。想知道“工作单元”是完成还是失败:可以。想要返回一个值:可以。想要动态地将某些任务优先于其他任务?当然。需要安排任务的能力?可以做。以此类推。

      Callables 替换您的Runnables(这很简单,两者都是单一方法接口!),停止操纵Threads 以支持Futures 并将管道留给@987654335 @。

      我怀疑 Callable 是否能够做 Runnable 的所有事情,为什么这么多人使用 Runnable 而不是 callable?

      也许他们确实有旧代码(Java 1.4?)。也许他们没有意识到更高级别抽象的好处,而是更喜欢低级别的Thread 东西?

      一般来说,既然并发 API 来了,绝对没有理由更喜欢使用Threads。

      与Runnable接口相比,实现Callable接口是否有额外的开销?

      在“实现Callable”与Runnable 中,没有,没有。但是新的Callable 东西是有成本的,因为在内部,这一切都归结为Threads 和Runnables(至少,当前的实现是这样做的)。但您实际上可能会获得性能提升,因为有了更简单的线程重用等新功能!

      所以,是的,并发 API 有其成本,但它在任何标准用例中绝对完全可以忽略不计,但它也有新的优势,使其在许多方面都变得更好,包括性能。

      此外,您还可以从 API 中获得大量新的可能性,如前所述(参见 Fork/Join 框架,参见 Java 8 中的并行流,...),并减少对任何“自定义”扭结的需求,上述功能的“自制”并发代码,众所周知,这很难做到。

      收益/成本比完全有利于“新”并发 API。

      【讨论】:

        【解决方案4】:

        我怀疑 Callable 是否能够做 Runnable 的所有事情,为什么这么多人使用 Runnable 而不是 callable?与 Runnable 接口相比,实现 Callable 接口是否有额外的开销?

        1. 使用Runnable 接口进行即发即弃 调用,尤其是当您对任务执行的结果不感兴趣时​​。
        2. Callable 接口的实现没有额外的开销。

        与文档page的主要区别

        Callable 接口类似于Runnable,因为两者都是为实例可能由另一个线程执行的类设计的。但是,Runnable 不会返回结果,也不会抛出已检查的异常。

        让我们查看AbstractExecutorService的源代码

        public Future<?> submit(Runnable task) {
            if (task == null) throw new NullPointerException();
            RunnableFuture<Object> ftask = newTaskFor(task, null);
            execute(ftask);
            return ftask;
        }
        
        
        public <T> Future<T> submit(Callable<T> task) {
            if (task == null) throw new NullPointerException();
            RunnableFuture<T> ftask = newTaskFor(task);
            execute(ftask);
            return ftask;
        }
        

        由于Callable 内部使用RunnableFuture&lt;T&gt;,我看不到执行Callable 任务的任何开销

        【讨论】:

          【解决方案5】:

          我怀疑 Callable 是否能够做 Runnable 的所有事情,为什么这么多人使用 Runnable 而不是 callable?

          这个问题无异于问:“为什么 Java 有静态类型?”接口是编译时类型签名的声明,不多也不少;任何两个接口之间的唯一区别是参数和返回值的编译时类型。

          那么为什么 Java 有静态类型呢?不幸的是,这个问题超出了 StackOverflow 的范围。您可以使用 Google 查找有关静态类型语言与动态类型语言的所有信息。

          另外,如果您想了解一个不同的世界,您可以尝试编写一些 Ruby 代码。 Ruby 中没有接口,因为没有静态类型。 Ruby 程序员谈论“Duck Typing”,这对 Google 来说是另一个好词。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-08-04
            • 2020-08-30
            • 2021-09-01
            • 1970-01-01
            • 2012-03-26
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多