Разница между интерфейсами Runnable и Callable в Java - PullRequest
449 голосов
/ 26 сентября 2008

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

Ответы [ 12 ]

407 голосов
/ 26 сентября 2008

См. Объяснение здесь .

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

245 голосов
/ 17 октября 2010

Каковы различия в приложениях Runnable и Callable. Разница только с параметром возврата, представленным в Callable?

В основном да. Смотрите ответы на этот вопрос . И Javadoc для Callable.

Зачем иметь оба, если Callable может делать все, что Runnable делает?

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

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

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

77 голосов
/ 20 мая 2013
  • A 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;
    }
    
36 голосов
/ 27 января 2010

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

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

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

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

26 голосов
/ 03 октября 2014

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

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

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

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

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

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

14 голосов
/ 15 февраля 2016

Назначение этих интерфейсов из документации Oracle:

Интерфейс

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

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

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

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

    Пример:

    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. Тривиальная разница: имя метода для реализации => run() для Runnable и call() для Callable.

14 голосов
/ 27 декабря 2014

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

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 и вызовом 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. Объект 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);
11 голосов
/ 17 октября 2010

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

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

6 голосов
/ 09 октября 2017
+-------------------------------------+--------------------------------------------------------------------------------------------------+
|              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. источник

5 голосов
/ 02 октября 2017

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

  1. Callable представлен в JDK 5.0, а Runnable представлен в JDK 1.0
  2. У Callable есть метод call (), но у Runnable есть метод run ().
  3. У Callable есть метод call, который возвращает значение, но у Runnable есть метод run, который не возвращает никакого значения.
  4. метод вызова может выдать проверенное исключение, но метод run не может выдать проверенное исключение.
  5. Вызванный метод submit () для помещения в очередь задач, но Runnable метод execute () для помещения в очередь задач.
...