Pergunta

O que é a diferença entre usar as interfaces Runnable e Callable ao projetar um thread concorrente em Java, por que você iria escolher um sobre o outro?

Foi útil?

Solução

Veja a explicação aqui .

A interface Callable é semelhante ao Runnable, em que ambos são projetados para as classes cujas instâncias são potencialmente executado por outra fio. A Runnable, no entanto, não retornar um resultado e não pode jogar uma exceção verificada.

Outras dicas

Quais são as diferenças nas aplicações de Runnable e Callable. É a diferença apenas com o parâmetro de retorno presente em Callable?

Basicamente, sim. Veja as respostas para esta questão . E a javadoc para Callable .

O que é a necessidade de ter tanto se Callable pode fazer tudo o que Runnable faz?

Como a interface Runnable não pode fazer tudo o que Callable faz!

Runnable existe desde Java 1.0, mas Callable só foi introduzido em Java 1.5 ... para lidar com casos de uso que Runnable não suporta. Em teoria, a equipe de Java poderia ter mudado a assinatura do método Runnable.run(), mas isso teria quebrado a compatibilidade binária com código pré-1.5, exigindo recodificação ao migrar o código Java velho para JVMs mais recentes. Isso é um grande não-não. Java se esforça para ser compatível ... e isso tem sido um dos maiores pontos de venda do Java para o negócio de computação.

E, obviamente, há casos de uso em que uma tarefa não necessidade para retornar um resultado ou lançar uma exceção verificada. Para os casos de uso, usando Runnable é mais conciso do que usar Callable<Void> e retornar um valor fictício (null) a partir do método call().

  • Callable precisa de um para implementar o método call() enquanto um Runnable necessidades para implementar o método run().
  • A Callable pode retornar um valor, mas um Runnable não pode.
  • A Callable pode lançar exceção verificada, mas um Runnable não pode.
  • A Callable pode ser usado com métodos ExecutorService#invokeXXX(Collection<? extends Callable<T>> tasks) mas um Runnable não pode ser.

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

Eu encontrei isso em outro blog que pode explicar um pouco mais estes diferenças :

Embora ambos os interfaces são implementadas pelas classes que desejam executar em um segmento diferente da execução, mas há algumas diferenças entre os dois de interface que são:

  • Um exemplo Callable<V> retorna um resultado do tipo V, enquanto uma instância Runnable não.
  • Uma instância Callable<V> pode lançar exceções verificadas, enquanto uma instância Runnable não pode

Os designers de Java sentiu a necessidade de estender as capacidades da interface Runnable, mas eles não queriam afetar os usos da interface Runnable e provavelmente essa era a razão pela qual eles foram para ter uma interface separada chamada Callable em Java 1.5 do que mudar o Runnable já existente.

Vejamos onde se poderia usar Runnable e mobilizável.

Runnable e mobilizável ambos executados em um segmento diferente do que o segmento chamado. Mas mobilizável pode retornar um valor e Runnable não pode. Então, de onde é que isto se aplica realmente.

Runnable : Se você tem um incêndio e esquecer tarefa, em seguida, usar Runnable. Colocar o seu código dentro de um Runnable e quando o método run () é chamado, você pode realizar sua tarefa. O segmento de chamada realmente não se importa quando você executar sua tarefa.

Callable : Se você está tentando recuperar um valor de uma tarefa, em seguida, usar mobilizável. Agora pode ser chamado em sua própria vontade não fazer o trabalho. Você vai precisar de um futuro que você envolver em torno de seu mobilizável e obter seus valores em future.get (). Aqui, o segmento de chamada será bloqueado até que o futuro volta com resultados que por sua vez está à espera de chamada do mobilizável () para executar.

Então, pense sobre uma interface para uma classe de destino onde você tem tanto Runnable e mobilizável envolveu métodos definidos. A classe chamando vai chamar aleatoriamente os seus métodos de interface sem saber qual é Runnable e que é exigível. Os métodos Execut�eis será executado de forma assíncrona, até que um método mobilizável é chamado. Aqui fio da classe chamando irá bloquear desde que você está recuperando os valores de sua classe alvo.

NOTA: Dentro de sua classe de destino você pode fazer as chamadas para mobilizável e Runnable em um único executor fio, tornando este mecanismo semelhante a uma fila de envio serial. Então, enquanto o chamador liga para o Runnable envolveu métodos o segmento chamado executará muito rápido sem bloqueio. Assim que chama uma mobilizável envolto em método Futuro ela terá de bloco até que todos os outros itens na fila são executados. Só então o método retornará com valores. Este é um mecanismo de sincronização.

interface de Callable declara método call() e você precisa fornecer genéricos como tipo de chamada Object () deve retornar -

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 por outro lado é a interface que declara método run() que é chamado quando você criar um segmento com o início executável e call () nele. Você pode também diretamente chamada run (), mas isso só executa o método run () é mesmo segmento.

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();
}

Para resumir alguns diferença notável são

  1. Um objeto Runnable não retorna um resultado enquanto um objeto Callable retorna um resultado.
  2. Um objeto Runnable não pode lançar uma exceção verificada wheras um objeto Callable pode lançar uma exceção.
  3. A interface Runnable existe desde Java 1.0 enquanto Callable só foi introduzido em Java 1.5.

Poucas semelhanças incluem

  1. instâncias das classes que implementam Runnable ou interfaces de resgatáveis ??são potencialmente executado por outro segmento.
  2. Instância de ambos mobilizável e interfaces de Runnable pode ser executado por ExecutorService via submit () método.
  3. Ambos são interfaces funcionais e pode ser usado em expressões lambda desde Java8.

Os métodos na interface ExecutorService são

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

Objetivo dessas interfaces de documentação do Oracle:

Runnable interface deve ser implementado por qualquer classe cujas instâncias são destinados a ser executado por um Thread. A classe deve definir um método sem argumentos chamados run.

mobilizável : A tarefa que retorna um resultado e pode lançar uma exceção. Os implementadores definir um único método sem argumentos chamados chamada. A interface Callable é semelhante ao Runnable, em que ambos são projetados para as classes cujas instâncias são potencialmente executado por outro segmento. A Runnable, no entanto, não retorna um resultado e não pode lançar uma exceção verificada.

Outras diferenças:

  1. Você pode passar Runnable para criar uma Passe . Mas você não pode criar novo tópico passando Callable como parâmetro. Você pode passar mobilizável apenas para casos ExecutorService.

    Exemplo:

    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. Use Runnable para o fogo e esquecer chamadas. Uso Callable para verificar o resultado.

  3. Callable pode ser passado para invokeAll método diferente de Runnable. Métodos invokeAny e invokeAll executar as formas mais comumente útil de execução em massa, a execução de um conjunto de tarefas e, em seguida, à espera de pelo menos um, ou todos, para completar

  4. Trivial diferença:. Nome do método a ser implementado => run() para Runnable e call() para Callable

Como já foi mencionado aqui mobilizável é relativamente nova interface e foi introduzido como parte do pacote de concorrência. Ambos mobilizável e Runnable pode ser usado com executores. Tópico Class (que implementa Runnable em si) suporta Runnable somente.

Você ainda pode usar Runnable com executores. A vantagem de mobilizável que você pode enviá-lo para executor e imediatamente obter resultado de volta futuro que será atualizado quando a execução for concluída. O mesmo pode ser implementado com Runnable, mas neste caso você tem que gerenciar os resultados você mesmo. Por exemplo, você pode criar resultados fila que vai realizar todos os resultados. Outro thread pode esperar nessa fila e lidar com os resultados que chegam.

+-------------------------------------+--------------------------------------------------------------------------------------------------+
|              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                                                                     |
+-------------------------------------+--------------------------------------------------------------------------------------------------+

Os designers de Java senti uma necessidade de estender as capacidades da interface Runnable, mas eles não queriam afetar os usos da interface Runnable e provavelmente essa era a razão pela qual eles passaram por ter uma interface separada chamado Callable em Java 1.5 do que mudar a interface Runnable já existente, que tem sido uma parte de Java desde Java 1.0. fonte

Diferença entre mobilizável e Runnable são os seguintes:

  1. mobilizável é introduzido no JDK 5.0, mas Runnable é introduzido no JDK 1.0
  2. mobilizável tem método call (), mas Runnable tem método run ().
  3. mobilizável tem chamada de método que retorna valor, mas Runnable foi executado método que não retorna nenhum valor.
  4. chamada de método pode lançar exceção verificada, mas executar método não pode lançar exceção verificada.
  5. uso mobilizável enviar método () para colocar em fila de tarefas mas o uso Runnable método execute () para colocar na fila de tarefas.

mobilizável e Runnable ambos é semelhante a outro e pode usar na implementação de rosca. Em caso de implementação de Runnable você deve implementar run () método, mas em caso de exigível você tem necessidade de implementar call () método, tanto método obras de formas semelhantes, mas que pode ser chamado call () método tem mais flexibility.There é algumas diferenças entre eles.

Diferença entre Runnable e exigível como below--

1) O run () método de executável retorna vazio , significa que se você quiser que o seu fio de retorno algo que você pode usar ainda mais, em seguida, você tem nenhuma escolha com prazo Runnable () método. Há uma solução 'mobilizável' , Se você quiser devolver qualquer coisa em forma de objeto , então você deve usar mobilizável em vez de Runnable . interface chamável tem método 'call ()' que retorna objeto .

Método de assinatura - Runnable->

public void run(){}

Callable->

public Object call(){}

2) Em caso de run Runnable () método se qualquer exceção verificada surge então você deve necessidade de tratado com o bloco try catch , mas em caso de chamada mobilizável () método que você exceção pode jogar verificados como abaixo

 public Object call() throws Exception {}

3) Runnable vem do legado java 1.0 versão, mas exigível veio em Java 1.5 versão com < strong> Executer quadro.

Se você está familiarizado com Executers , então você deve uso mobilizável em vez de Runnable .

Hope você entende.

Runnable (vs) Callable entra em ponto quando estamos usando quadro Executer.

ExecutorService é uma subinterface de Executor , que aceita tanto tarefas resgatáveis ??Runnable e.

No início multi-threading pode ser conseguido usando interface Runnable Desde 1.0 , mas ali o problema depois de completar a tarefa fio somos incapazes para coletar as informações Threads. Em ordem para coletar os dados, podemos usar campos estáticos.

Exemplo segmentos separados para coletar cada dados do aluno.

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() );
}

Para resolver este problema eles introduziram Callable<V> Desde 1.5 , que retorna um resultado e pode lançar uma exceção.

  • Single método abstrato :. Ambos mobilizável e interface Runnable ter um método abstrato único, o que significa que pode ser usado em expressões lambda em Java 8

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

Existem algumas maneiras diferentes de delegar tarefas para execução a um ExecutorService .

  • execute(Runnable task):void grades novos fios, mas não bloqueia thread principal ou segmento chamador como este método de retorno void.
  • submit(Callable<?>):Future<?>, submit(Runnable):Future<?> crates nova linha e blocos de thread principal quando você estiver usando future.get () .

Exemplo de utilização de interfaces Executel, mobilizável com quadro 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();
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top