2008-09-26 8 views
378

¿Cuál es la diferencia entre utilizar las interfaces Ejecutable e Invocable cuando se diseña un subproceso simultáneo en Java, por qué elegir uno sobre el otro?La diferencia entre las interfaces Ejecutable e Invocable en Java

+2

Para discusión adicional, después de leer esta página, vea [¿Se puede preferir el Callable sobre Runnable?] (Http://stackoverflow.com/q/16757142/1005481) –

Respuesta

357

Ver la explicación here.

la interfaz invocable es similar a Ejecutable, en que ambos están diseñados para las clases cuyas instancias están potencialmente ejecutado por otro hilo. A Runnable, sin embargo, no devuelve un resultado y no se puede lanzar una excepción marcada .

31

me encontré con esto en otro blog que puede explicarlo un poco más estos differences:

Aunque las interfaces son implementadas por las clases que desean ejecutar en un subproceso diferente de la ejecución, pero hay pocas diferencias entre los dos interfaz que son:

  • a Callable<V> ejemplo devuelve un resultado de tipo V, mientras que un ejemplo Runnable no lo hace.
  • Un Callable<V> instancia puede lanzar excepciones controladas, mientras que una instancia Runnable no pueden

Los diseñadores de Java sentido la necesidad de extender las capacidades de la interfaz Runnable, pero ellos no quieren afectar a los usos de la interfaz Runnable y, probablemente, esa fue la razón por la que optaron por tener una interfaz separada llamada Callable en Java 1.5 que cambiar la ya existente Runnable.

223

¿Cuáles son las diferencias en las aplicaciones de Runnable y Callable? ¿La diferencia es solo con el parámetro de retorno presente en Callable?

Básicamente, sí. Ver las respuestas al this question. Y el javadoc for Callable.

¿Cuál es la necesidad de tener ambas si Callable puede hacer todo eso Runnable?

Debido a que la interfaz de Runnableno puede hacer todo lo queCallable hace!

Runnable ha estado presente desde Java 1.0, pero Callable solo se introdujo en Java 1.5 ... para manejar casos de uso que Runnable no admite. En teoría, el equipo de Java podría haber cambiado la firma del método Runnable.run(), pero esto habría roto la compatibilidad binaria con el código pre-1.5, requiriendo la recodificación al migrar el antiguo código Java a las JVM más nuevas. Eso es un GRAN NO-NO. Java se esfuerza por ser compatible con versiones anteriores ... y ese ha sido uno de los mayores puntos de venta de Java para la informática empresarial.

Y, obviamente, hay casos de uso donde una tarea no requiere para devolver un resultado o lanzar una excepción marcada. Para esos casos de uso, usar Runnable es más conciso que usar Callable<Void> y devolver un valor ficticio (null) del método call().

+4

Me pregunto de dónde sacaste este historial. Esto es muy útil – spiderman

+3

@prash - los hechos básicos se encuentran en los libros de texto antiguos. Al igual que la primera edición de Java in a Nutshell. –

+1

(@prash - También ... comenzando a usar Java en la era de Java 1.1.) –

8

Como ya se ha mencionado aquí, Callable es una interfaz relativamente nueva y se introdujo como parte del paquete de simultaneidad. Tanto Callable como Runnable se pueden usar con ejecutores. Class Thread (que implementa Runnable en sí) solo admite Runnable.

Aún puede usar Runnable con ejecutores. La ventaja de Callable es que puede enviarlo al ejecutor e inmediatamente recuperar el resultado futuro que se actualizará cuando finalice la ejecución. Lo mismo se puede implementar con Runnable, pero en este caso debe administrar los resultados usted mismo. Por ejemplo, puede crear una cola de resultados que contendrá todos los resultados. Otro hilo puede esperar en esta cola y lidiar con los resultados que llegan.

+0

Me pregunto cuál es el ejemplo de una excepción de lanzamiento de subprocesos en Java. ¿Podrá el hilo principal atrapar esa excepción? Si no, no usaría Llamada. Alex, ¿tienes alguna idea sobre esto? ¡Gracias! – trillions

+1

El código que se ejecuta en una secuencia personalizada como cualquier otro código puede generar una excepción. Para atraparlo en otro hilo, debe realizar algunos esfuerzos, ya sea mediante un mecanismo de notificación personalizado (por ejemplo, basado en oyentes) o mediante el uso de 'Futuro' o agregando un gancho que capte todas las excepciones pendientes: http://docs.oracle.com/javase /6/docs/api/java/lang/Thread.html#setDefaultUncaughtExceptionHandler% 28java.lang.Thread.UncaughtExceptionHandler% 29 – AlexR

+0

¡Excelente información! Gracias, Alex! :) – trillions

63
  • Un Callable necesita implementar call() método, mientras que un Runnable necesita implementar run() método.
  • A Callable puede devolver un valor pero Runnable no puede.
  • A Callable puede arrojar una excepción comprobada, pero Runnable no puede.
  • A Callable puede usarse con los métodos ExecutorService#invokeXXX(Collection<? extends Callable<T>> tasks) pero no puede ser Runnable.

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

ExecutorService.submit (tarea ejecutable) también existe y es muy útil –

+0

Runnable también se puede usar con ExecutorService de las siguientes maneras: 1) ExecutorService.execute (Ejecutable) 2) ExecutorService.submit (Ejecutable) –

+0

También está Executor.submit (tarea Llamable ) pero no puede invocarAll o invokeAny con la colección de tareas Ejecutables Collection > – nikli

21

Veamos donde se podría utilizar Ejecutable y rescatable.

Ejecutable y llamable ambos se ejecutan en un subproceso diferente de la cadena de llamada. Pero Callable puede devolver un valor y Runnable no. Entonces, ¿dónde se aplica esto realmente?

Ejecutable: Si tiene una tarea de desencadenar y olvidar, utilice Runnable. Coloque su código dentro de Runnable y cuando se llame al método run(), puede realizar su tarea. Al hilo de llamada realmente no le importa cuando realiza su tarea.

Llamable: Si está tratando de recuperar un valor de una tarea, utilice Callable. Ahora invocable por sí solo no hará el trabajo. Necesitará un futuro que envuelva su llamador y obtenga sus valores en future.get(). Aquí, el hilo de llamada será bloqueado hasta que el futuro regrese con resultados, que a su vez está esperando que se ejecute el método call() de Callable.

Por lo tanto, piense en una interfaz para una clase de destino en la que tenga definidos tanto los métodos ejecutables como los ejecutables. La clase llamante llamará aleatoriamente a sus métodos de interfaz sin saber cuál es Runnable y cuál es invocable. Los métodos Runnable se ejecutarán de forma asíncrona, hasta que se llame a un método invocable. Aquí el hilo de la clase llamante se bloqueará ya que está recuperando valores de su clase objetivo.

NOTA: Dentro de su clase de destino puede realizar las llamadas a Callable y Runnable en un único ejecutor de subprocesos, haciendo que este mecanismo sea similar a una cola de despacho en serie. De modo que, mientras la persona que llama llame a sus métodos envueltos en Runnable, el hilo de llamada se ejecutará realmente rápido sin bloqueo.Tan pronto como llame a un método de inclusión invocable en el futuro, tendrá que bloquear hasta que se ejecuten todos los demás elementos en cola. Solo entonces el método regresará con valores. Este es un mecanismo de sincronización.

14

Callable interfaz declara call() método y lo que necesita para proporcionar los genéricos como tipo de llamada Object() debe devolver -

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 el contrario es la interfaz que declara run() método que se llama cuando se crea una Enhebre con el ejecutable y llame a start() en él. También puede llamar directamente a run() pero eso solo ejecuta el método run() es el mismo hilo.

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 algunas diferencias notables son

  1. Runnable Un objeto no devuelve un resultado, mientras que un objeto Callable devuelve un resultado.
  2. Un objeto Runnable no puede arrojar una excepción marcada cuando un objeto Callable puede lanzar una excepción .
  3. La interfaz Runnable ha existido desde Java 1.0, mientras que Callable solo se introdujo en Java 1.5.

algunas similitudes incluyen

  1. instancias de las clases que implementan interfaces de Ejecutables o se puede llamar son potencialmente ejecutado por otro hilo.
  2. La instancia de las interfaces ejecutables y ejecutables se puede ejecutar mediante ExecutorService mediante el método submit().
  3. Ambas son interfaces funcionales y se pueden usar en expresiones Lambda desde Java8.

Métodos en interfaz ExecutorService son

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

Propósito de estas interfaces de documentación de Oracle:

interfaz

Runnable debe ser implementado por cualquier clase cuyas instancias están destinados a ser ejecutado por un Thread. La clase debe definir un método sin argumentos llamado run.

Callable: una tarea que devuelve un resultado y puede arrojar una excepción. Los implementadores definen un único método sin argumentos llamado llamada. La interfaz Callable es similar a Runnable, en que ambos están diseñados para clases cuyas instancias se ejecutan potencialmente por otro hilo. Un Runnable, sin embargo, no devuelve un resultado y no puede arrojar una excepción marcada.

Otras diferencias:

  1. Usted puede pasar Runnable para crear un Thread. Pero no puede crear un nuevo hilo pasando Callable como parámetro. Puede pasar Callable solo a instancias 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. Use Runnable de fuego y olvidar las llamadas. Use Callable para verificar el resultado.

  3. Callable se puede pasar al método invokeAll a diferencia de Runnable. Métodos invokeAny y invokeAll realizan las formas más comúnmente útil de ejecución a granel, la ejecución de un conjunto de tareas y, a continuación a la espera de al menos uno, o todos, para completar

  4. diferencia Trivial: nombre del método que se aplicará =>run() para Runnable y call() para Callable.

1

Diferencia entre Callable y Ejecutable están siguiendo:

  1. Callable se introduce en JDK 5.0 pero Ejecutable se introduce en JDK 1.0
  2. Callable tiene método call() pero Ejecutable ha ejecutar () método.
  3. Llamada tiene método de llamada que devuelve valor, pero el método de ejecución ejecutable no devuelve ningún valor.
  4. método de llamada puede arrojar excepción comprobada, pero el método de ejecución no puede arrojar la excepción comprobada.
  5. Método de envío utilizable() para poner en la cola de tareas, pero Runnable usa el método execute() para poner en la cola de tareas.
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                  | 
+-------------------------------------+--------------------------------------------------------------------------------------------------+ 

Los diseñadores de Java sintieron la necesidad de extender las capacidades de la interfaz Runnable, pero que no querían afectar a los usos de la interfaz Runnable y probablemente esa fue la razón por la que fuimos a tener una interfaz separada llamada Callable en Java 1.5 que cambiar la interfaz Runnable ya existente que ha sido una parte de Java desde Java 1.0. source

Cuestiones relacionadas