Вопрос:

Разница между интерфейсами Runnable и Callable в Java

java multithreading interface runnable callable

253675 просмотра

12 ответа

2918 Репутация автора

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

Автор: Scottm Источник Размещён: 26.09.2008 07:00

Ответы (12)


407 плюса

76619 Репутация автора

Решение

Смотрите объяснение здесь .

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

Автор: Jorge Ferreira Размещён: 26.09.2008 07:02

36 плюса

794 Репутация автора

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

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

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

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

Автор: amoran Размещён: 27.01.2010 05:35

245 плюса

533989 Репутация автора

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

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

Зачем нужны оба, если 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>и возврат значения dummy ( null) из call()метода.

Автор: Stephen C Размещён: 17.10.2010 06:44

11 плюса

100159 Репутация автора

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

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

Автор: AlexR Размещён: 17.10.2010 07:16

77 плюса

1398 Репутация автора

  • CallableНеобходимо реализовать call()метод в то время как Runnableнеобходимо реализовать run()метод.
  • A Callableможет вернуть значение, но Runnableне может.
  • 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;
    }
    
Автор: nikli Размещён: 20.05.2013 01:34

26 плюса

1327 Репутация автора

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

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

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

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

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

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

Автор: Kris Subramanian Размещён: 03.10.2014 04:40

14 плюса

44036 Репутация автора

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 &lt;code&gt;Runnable&lt;/code&gt; is used 
     * to create a thread, starting the thread causes the object's 
     * run method to be called in that separately executing 
     * thread. 
     * 

* The general contract of the method run 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);
Автор: Aniket Thakur Размещён: 27.12.2014 07:24

14 плюса

31581 Репутация автора

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

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

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

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

  1. Вы можете перейти Runnableк созданию темы . Но вы не можете создать новый поток, передавая в 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.

Автор: Ravindra babu Размещён: 15.02.2016 10:59

5 плюса

702 Репутация автора

Разница между 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 () для помещения в очередь задач, но запускаемое использование метода execute () для помещения в очередь задач.
Автор: Raman Gupta Размещён: 02.10.2017 09:47

6 плюса

34086 Репутация автора

+-------------------------------------+--------------------------------------------------------------------------------------------------+
|              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. источник

Автор: Premraj Размещён: 08.10.2017 10:43

2 плюса

49 Репутация автора

Callable и Runnable оба похожи друг на друга и могут использовать в реализации потока. В случае реализации Runnable вы должны реализовать метод run (), но в случае вызываемого необходимо реализовать метод call () , оба метода работают одинаково, но метод вызываемого вызова () обладает большей гибкостью. Между ними есть некоторые различия.

Разница между Runnable и вызываемым , как below--

1) Run () метод работоспособных возвращает недействительным , означает , что если вы хотите , чтобы ваш обратный поток то , что вы можете использовать в дальнейшем , то у вас нет иного выбора , с Runnable Run () метод. Существует решение «Callable». Если вы хотите вернуть какую-либо вещь в виде объекта, вам следует использовать Callable вместо Runnable . В вызываемом интерфейсе есть метод call (), который возвращает Object .

Подпись метода - Runnable->

public void run(){}

Callable->

public Object call(){}

2) В случае использования метода Runnable run (), если возникает какое-либо проверенное исключение, вам необходимо обработать блок try catch , но в случае вызова метода Callable () вы можете выбросить проверенное исключение, как показано ниже

 public Object call() throws Exception {}

3) Runnable поставляется с устаревшей версией java 1.0 , но функция callable появилась в версии Java 1.5 с платформой Executer .

Если вы знакомы с Executers, вам следует использовать Callable вместо Runnable .

Надеюсь, вы понимаете.

Автор: Sudhakar Pandey Размещён: 23.10.2018 08:12

0 плюса

5011 Репутация автора

Runnable (против) Callable вступает в силу, когда мы используем среду исполнения.

ExecutorService - это подинтерфейс Executor, который принимает задачи Runnable и Callable.

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

Пример Отдельные темы для сбора данных о каждом ученике.

static HashMap<String, List> multiTasksData = new HashMap();
public static void main(String[] args) {
    Thread t1 = new Thread( new RunnableImpl(1), "T1" );
    Thread t2 = new Thread( new RunnableImpl(2), "T2" );
    Thread t3 = new Thread( new RunnableImpl(3), "T3" );

    multiTasksData.put("T1", new ArrayList() ); // later get the value and update it.
    multiTasksData.put("T2", new ArrayList() );
    multiTasksData.put("T3", new ArrayList() );
}

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

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

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

Есть несколько различных способов делегировать задачи для выполнения в ExecutorService .

  • execute(Runnable task):void создает новый поток, но не блокирует основной поток или поток вызывающего, так как этот метод возвращает void.
  • submit(Callable<?>):Future<?>, submit(Runnable):Future<?>Ящики новую нить и блоки основной нити при использовании future.get () .

Пример использования интерфейсов Runnable, Callable с платформой Executor.

class CallableTask implements Callable<Integer> {
    private int num = 0;
    public CallableTask(int num) {
        this.num = num;
    }
    @Override
    public Integer call() throws Exception {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + " : Started Task...");

        for (int i = 0; i < 5; i++) {
            System.out.println(i + " : " + threadName + " : " + num);
            num = num + i;
            MainThread_Wait_TillWorkerThreadsComplete.sleep(1);
        }
        System.out.println(threadName + " : Completed Task. Final Value : "+ num);

        return num;
    }
}
class RunnableTask implements Runnable {
    private int num = 0;
    public RunnableTask(int num) {
        this.num = num;
    }
    @Override
    public void run() {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + " : Started Task...");

        for (int i = 0; i < 5; i++) {
            System.out.println(i + " : " + threadName + " : " + num);
            num = num + i;
            MainThread_Wait_TillWorkerThreadsComplete.sleep(1);
        }
        System.out.println(threadName + " : Completed Task. Final Value : "+ num);
    }
}
public class MainThread_Wait_TillWorkerThreadsComplete {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        System.out.println("Main Thread start...");
        Instant start = java.time.Instant.now();

        runnableThreads();
        callableThreads();

        Instant end = java.time.Instant.now();
        Duration between = java.time.Duration.between(start, end);
        System.out.format("Time taken : %02d:%02d.%04d \n", between.toMinutes(), between.getSeconds(), between.toMillis()); 

        System.out.println("Main Thread completed...");
    }
    public static void runnableThreads() throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(4);
        Future<?> f1 = executor.submit( new RunnableTask(5) );
        Future<?> f2 = executor.submit( new RunnableTask(2) );
        Future<?> f3 = executor.submit( new RunnableTask(1) );

        // Waits until pool-thread complete, return null upon successful completion.
        System.out.println("F1 : "+ f1.get());
        System.out.println("F2 : "+ f2.get());
        System.out.println("F3 : "+ f3.get());

        executor.shutdown();
    }
    public static void callableThreads() throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(4);
        Future<Integer> f1 = executor.submit( new CallableTask(5) );
        Future<Integer> f2 = executor.submit( new CallableTask(2) );
        Future<Integer> f3 = executor.submit( new CallableTask(1) );

        // Waits until pool-thread complete, returns the result.
        System.out.println("F1 : "+ f1.get());
        System.out.println("F2 : "+ f2.get());
        System.out.println("F3 : "+ f3.get());

        executor.shutdown();
    }
}
Автор: Yash Размещён: 03.06.2019 09:54
Вопросы из категории :
32x32