2008-09-26 2 views
378

В чем разница между использованием интерфейсов Runnable и Callable при разработке параллельного потока в Java, почему вы выбрали один из них?Разница между интерфейсами Runnable и Callable в Java

+2

Для дополнительной информации, прочитав эту страницу, см. [Может ли быть отзывчивым предпочтительнее Runnable?] (Http://stackoverflow.com/q/16757142/1005481) – 2013-06-18 08:04:00

ответ

357

См. Пояснения here.

отзывной интерфейс похож на Runnable, в том, что оба они предназначены для классов, экземпляры потенциально выполнены другим нити. A Runnable, однако, не возвращает результат и не может выполнить исключение с проверкой .

31

Я нашел это в другом блоге, что может объяснить это немного больше этих differences:

Хотя оба интерфейсы реализованы классами, которые желают выполнить в другом потоке исполнения, но несколько различий между этими двумя интерфейсом, которые являются:

  • Callable<V> экземпляр возвращает результат типа V, в то время как Runnable экземпляр не делает.
  • Callable<V> экземпляр может бросить проверенные исключения, в то время как Runnable например, не может

Разработчики Java почувствовал необходимость расширения возможностей интерфейса Runnable, но они не хотят, чтобы повлиять на использование интерфейса Runnable, и, вероятно, именно поэтому они решили использовать отдельный интерфейс с именем Callable в Java 1.5, вместо изменения уже существующего Runnable.

223

В чем разница в приложениях Runnable и Callable. Разница только с параметром возврата, присутствующим в Callable?

В принципе, да. См. Ответы на вопрос this question. И javadoc for Callable.

Что является необходимость наличия как если Callable может делать все, что Runnable делает?

Поскольку интерфейс Runnableне может делать все, что делает Callable!

Runnable был вокруг с Java 1.0, но Callable был введен только в Java 1.5 ... для обработки пресетов, которые Runnable не поддерживает. Теоретически, команда Java могла бы изменить подпись метода Runnable.run(), но это сломало бы бинарную совместимость с кодом pre-1.5, требуя перекодировки при переносе старого кода Java на более новые JVM. Это БОЛЬШОЙ НЕТ-НЕТ. Java стремится к обратному совместимости ... и это была одна из самых больших точек продажи Java для бизнес-вычислений.

И, очевидно, существуют прецеденты, где задача не нужна, чтобы вернуть результат или выбросить проверенное исключение. Для этих прецедентов использование Runnable является более кратким, чем использование Callable<Void> и возвращает значение манекена (null) из метода call().

+4

Интересно, откуда вы взяли эту историю. Это очень полезно. – spiderman 2014-05-06 14:36:21

+3

@prash - основные факты можно найти в старых учебниках. Как и первое издание Java в двух словах. – 2014-05-29 11:40:37

+1

(@prash - также ..., начинающий использовать Java в эпоху Java 1.1). – 2015-10-23 22:43:23

8

Как уже говорилось, Callable - это относительно новый интерфейс, и он был представлен как часть пакета параллелизма. Оба Callable и Runnable могут использоваться с исполнителями. Класс Thread (который реализует Runnable) поддерживает только Runnable.

Вы все еще можете использовать Runnable с исполнителями. Преимущество Callable в том, что вы можете отправить его исполнителю и сразу же получить обратно. Результат в будущем, который будет обновлен после завершения выполнения. То же самое можно реализовать с помощью Runnable, но в этом случае вам нужно самостоятельно управлять результатами. Например, вы можете создать очередь результатов, которая будет содержать все результаты. Другая цепочка может ждать в этой очереди и обрабатывать результаты, которые приходят.

63
  • Callable необходимо реализовать метод call() в то время как Runnable необходимо реализовать метод run().
  • A Callable может вернуть значение, но Runnable не может.
  • A Callable может выдавать проверенное исключение, но Runnable не может.
  • A Callable может использоваться с методами ExecutorService#invokeXXX(Collection<? extends Callable<T>> tasks), но Runnable не может быть.

    public interface Runnable { 
        void run(); 
    } 
    
    public interface Callable<V> { 
        V call() throws Exception; 
    } 
    
21

Давайте посмотрим, где можно было бы использовать Runnable и Callable.

Runnable and Callable оба работают в другом потоке, кроме вызывающего потока. Но Callable может вернуть значение, а Runnable не может. Итак, где это действительно применимо.

Runnable: Если у вас есть огонь и задача забыть, используйте Runnable. Поместите свой код внутри Runnable и когда вызывается метод run(), вы можете выполнить свою задачу. Называющий поток действительно не волнует, когда вы выполняете свою задачу.

Вызываемый: Если вы пытаетесь получить значение из задачи, используйте функцию Callable. Теперь вызываемый сам по себе не будет выполнять эту работу. Вам понадобится будущее, которое вы обернете вокруг своего Callable и получите свои ценности в future.get(). Здесь вызывающий поток будет заблокирован до тех пор, пока будущее не вернется с результатами, которые, в свою очередь, ждут вызова метода Callable's() для выполнения.

Так что подумайте о интерфейсе к целевому классу, в котором определены оба метода Runnable и Callable wrapped. Вызывающий класс будет случайным образом вызывать ваши методы интерфейса, не зная, что является Runnable и который является Callable. Методы Runnable будут выполняться асинхронно, пока не будет вызван метод Callable. Здесь поток вызывающего класса будет блокироваться, так как вы извлекаете значения из вашего целевого класса.

ПРИМЕЧАНИЕ. Внутри вашего целевого класса вы можете выполнять вызовы Callable и Runnable на одном исполнителе потока, делая этот механизм похожим на очередность последовательной отправки. Таким образом, до тех пор, пока вызывающий вызов вызывает ваши Runnable wrapped methods, вызывающий поток будет выполняться очень быстро, не блокируя.Как только он вызовет Callable, завернутый в метод Future, он будет заблокирован до тех пор, пока не будут выполнены все остальные очереди. Только тогда метод вернется со значениями. Это механизм синхронизации.

14

Callable интерфейс объявляет call() метод, и вы должны предоставить дженерики как тип вызова Object() должен возвращать -

public interface Callable<V> { 
    /** 
    * Computes a result, or throws an exception if unable to do so. 
    * 
    * @return computed result 
    * @throws Exception if unable to compute a result 
    */ 
    V call() throws Exception; 
} 

Runnable с другой стороны, является интерфейс, который объявляет run() метод, который вызывается при создании Поток с runnable и call start() на нем. Вы также можете напрямую вызвать run(), но это просто выполнение метода run() - это тот же поток.

public interface Runnable { 
    /** 
    * When an object implementing interface <code>Runnable</code> is used 
    * to create a thread, starting the thread causes the object's 
    * <code>run</code> method to be called in that separately executing 
    * thread. 
    * <p> 
    * The general contract of the method <code>run</code> is that it may 
    * take any action whatsoever. 
    * 
    * @see  java.lang.Thread#run() 
    */ 
    public abstract void run(); 
} 

Суммируя несколько заметных разностной

  1. Runnable объект не возвращает результат, тогда как Callable объект возвращает результат.
  2. A Runnable объект не может выбросить проверенное исключение, поскольку объект Callable может выдать исключение .
  3. Интерфейс Runnable был рядом с Java 1.0, тогда как Callable был введен только в Java 1.5.

Немногие сходства включают

  1. экземпляров классов, которые реализуют Runnable или Callable интерфейсы являются потенциально выполняется другим потоком.
  2. Экземпляр интерфейсов Callable и Runnable может быть выполнен ExecutorService с помощью метода submit().
  3. Оба являются функциональными интерфейсами и могут использоваться в выражениях лямбда с Java8.

метода в интерфейсе ExecutorService является

<T> Future<T> submit(Callable<T> task); 
Future<?> submit(Runnable task); 
<T> Future<T> submit(Runnable task, T result); 
10

Целью этих интерфейсов от оракула документации:

Runnable интерфейс должен быть реализован любым классом, экземпляры которого предназначены для исполнения в Thread. Класс должен определить метод без аргументов, который называется run.

Callable: Задача, которая возвращает результат и может вызывать исключение. Разработчики определяют один метод без аргументов, называемых call. Интерфейс Callable похож на Runnable, поскольку оба они предназначены для классов, экземпляры которых потенциально выполняются другим потоком. A Runnable, однако, не возвращает результат и не может выставить проверенное исключение.

Другие отличия:

  1. Вы можете передать Runnable создать Thread. Но вы не можете создать новую тему, передав в качестве параметра Callable. Вы можете передать Callable только для ExecutorService экземпляров.

    Example:

    public class HelloRunnable implements Runnable { 
    
        public void run() { 
         System.out.println("Hello from a thread!"); 
        } 
    
        public static void main(String args[]) { 
         (new Thread(new HelloRunnable())).start(); 
        } 
    
    } 
    
  2. Runnable Используйте для огня и забыть звонки. Используйте Callable, чтобы проверить результат.

  3. Callable можно передать invokeAll способ не похоже Runnable. Методы invokeAny и invokeAll выполнять наиболее часто полезные формы насыпного исполнения, выполнение набора задач, а затем ждут, по крайней мере, один, или все, чтобы завершить

  4. Trivial разницы: имя метода реализовано =>run() для Runnable и call() за Callable.

1

Разница между Callable и Runnable следующие:

  1. Callable вводится в JDK 5.0, но Runnable вводится в JDK 1.0
  2. Callable имеет метод вызова(), но Runnable закончилась ().
  3. Callable имеет метод вызова, который возвращает значение, но метод вызова Callable не возвращает никакого значения.
  4. метод вызова может выдавать проверенное исключение, но метод run не может выставить проверенное исключение.
  5. Позволяет использовать метод submit() для включения очереди задач, но Runnable использует метод execute() для размещения в очереди задач.
3
+-------------------------------------+--------------------------------------------------------------------------------------------------+ 
|    Runnable    |           Callable<T>           | 
+-------------------------------------+--------------------------------------------------------------------------------------------------+ 
| Introduced in Java 1.0 of java.lang | Introduced in Java 1.5 of java.util.concurrent library           | 
| Runnable cannot be parametrized  | Callable is a parametrized type whose type parameter indicates the return type of its run method | 
| Runnable has run() method   | Callable has call() method                  | 
| Runnable.run() returns void   | Callable.call() returns a value of Type T              | 
| Can not throw Checked Exceptions | Can throw Checked Exceptions                  | 
+-------------------------------------+--------------------------------------------------------------------------------------------------+ 

Разработчики Java почувствовал необходимость расширения возможностей интерфейса Runnable, но они не хотят, чтобы повлиять на использование интерфейса Runnable и, вероятно, что и послужило причиной, почему они пошли за то, отдельный интерфейс с именем Callable в Java 1.5, чем изменение уже существующего интерфейса Runnable, который был частью Java с Java 1.0. source

Смежные вопросы