La diferencia entre las interfaces Runnable y Callable en Java

¿Cuál es la diferencia entre usar las interfaces Ejecutable e Invocable cuando se diseña un hilo concurrente en Java, por qué elegir uno sobre el otro?

Vea la explicación aquí .

La interfaz de llamada es similar a Runnable, en el sentido de que ambas están diseñadas 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.

  • A Callable necesita implementar el método call() mientras que Runnable necesita implementar el método run() .
  • Un Callable puede devolver un valor, pero un Runnable no puede.
  • Un Callable puede lanzar una excepción comprobada pero un Runnable no puede.
  • A Callable se puede usar con ExecutorService#invokeXXX(Collection> tasks) métodos pero Runnable no puede ser.

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

Encontré esto en otro blog que puede explicar un poco más estas diferencias :

Aunque ambas interfaces son implementadas por las clases que desean ejecutar en un hilo diferente de ejecución, pero hay algunas diferencias entre las dos interfaces que son:

  • Una Callable devuelve un resultado de tipo V , mientras que una instancia de Runnable no lo hace.
  • Una Callable puede lanzar excepciones comprobadas, mientras que una instancia de Runnable no puede

Los diseñadores de Java sintieron la necesidad de ampliar las capacidades de la interfaz Runnable , pero no quisieron afectar los usos de la interfaz Runnable y probablemente esa fue la razón por la que Callable por tener una interfaz separada denominada Callable en Java 1.5 que cambiando el Runnable ya existente.

Veamos donde uno usaría Runnable y Callable.

Runnable y Callable se ejecutan en un hilo diferente que el hilo de llamada. Pero Callable puede devolver un valor y Runnable no. Entonces, ¿dónde se aplica esto realmente?

Runnable : si tienes una tarea de fuego y olvídate, utiliza 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.

Invocable : si está intentando 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 objective 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 objective.

NOTA: Dentro de su clase objective, puede realizar las llamadas a Callable y Runnable en un solo ejecutor de hilos, 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 locking. 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.

Callable interfaz Callable declara el método call() y debe proporcionar generics como tipo de Object call () debería devolver –

 public interface Callable { /** * 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 otro lado, es la interfaz que declara el método run() que se llama cuando se crea un Thread con el ejecutable y se invoca 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 Runnable 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(); }

Para resumir algunas diferencias notables son

  1. Un objeto Runnable 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 de Runnable ha existido desde Java 1.0, mientras que Callable solo se introdujo en Java 1.5.

Algunas similitudes incluyen

  1. Las instancias de las clases que implementan interfaces ejecutables o invocables son ejecutadas potencialmente por otro hilo.
  2. La instancia de ambas interfaces, Callable y Runnable, puede ejecutarse por ExecutorService mediante el método submit ().
  3. Ambas son interfaces funcionales y se pueden usar en expresiones Lambda desde Java8.

Los métodos en la interfaz ExecutorService son

  Future submit(Callable task); Future submit(Runnable task);  Future submit(Runnable task, T result); 

Objetivo de estas interfaces de la documentación de Oracle:

La interfaz Runnable debe ser implementada por cualquier clase cuyas instancias estén destinadas a ser ejecutadas por un Thread . La clase debe definir un método sin argumentos llamado run .

Llamable : 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 de Callable es similar a Runnable , en el sentido de que ambas están diseñadas 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. Puede pasar Runnable para crear un hilo . Pero no puede crear un nuevo Thread al pasar Callable como parámetro. Puede pasar Callable solo a las instancias de ExecutorService .

    Ejemplo:

     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. Usa Runnable para disparar y olvida las llamadas. Use Callable para verificar el resultado.

  3. Callable puede pasar a invocar para invocar todo el método a diferencia de Runnable . Los métodos invokeAny e invokeAll realizan las formas más comunes de ejecución masiva, ejecutan una colección de tareas y luego esperan que al menos una, o todas, completen

  4. Diferencia trivial: nombre del método a implementar => run() para Runnable y call() para Callable .

Como ya se mencionó 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 puedes 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.

 +-------------------------------------+--------------------------------------------------------------------------------------------------+ | Runnable | Callable | +-------------------------------------+--------------------------------------------------------------------------------------------------+ | 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 ampliar las capacidades de la interfaz Runnable , pero no quisieron afectar los usos de la interfaz Runnable y probablemente esa fue la razón por la que Callable por tener una interfaz separada denominada Callable en Java 1.5 que cambiando la interfaz Runnable ya existente que ha sido parte de Java desde Java 1.0. fuente

La diferencia entre Callable y Runnable es la siguiente:

  1. Llamable se introduce en JDK 5.0 pero Runnable se presenta en JDK 1.0
  2. Callable tiene el método call () pero Runnable tiene el método run ().
  3. El método de llamada invocable devuelve valor pero Runnable tiene un método de ejecución que no devuelve ningún valor.
  4. El método de llamada puede arrojar una excepción comprobada, pero el método de ejecución no puede lanzar la excepción marcada.
  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.

Interfaz pública Ejecutable: la interfaz Ejecutable debe implementarse por cualquier clase cuyas instancias estén destinadas a ser ejecutadas por un hilo. La clase debe definir un método sin argumentos llamado ejecutar. Esta interfaz está diseñada para proporcionar un protocolo común para objetos que desean ejecutar código mientras están activos. Por ejemplo, Runnable se implementa por clase Thread. Estar activo simplemente significa que un hilo se ha iniciado y aún no se ha detenido.

Además, Runnable proporciona los medios para que una clase esté activa sin subclasificar el hilo. Una clase que implemente Runnable se puede ejecutar sin subclasificar el subproceso instanciando una instancia de subproceso y pasándose a sí mismo como el destino. En la mayoría de los casos, la interfaz Runnable se debe utilizar si solo planea anular el método run () y no otros métodos Thread. Esto es importante porque las clases no se deben subclasificar a menos que el progtwigdor tenga la intención de modificar o mejorar el comportamiento fundamental de la clase.

Desde: JDK1.0


interfaz pública que se puede llamar :

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 de llamada es similar a Runnable, en el sentido de que ambas están diseñadas 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.

La clase de ejecutores contiene métodos de utilidad para convertir desde otros formularios comunes a clases invocables.

Desde: JDK 1.5

Intereting Posts