La differenza tra le interfacce Runnable e Callable in Java

Qual è la differenza tra l’uso delle interfacce Runnable e Callable quando si progetta un thread concorrente in Java, perché scegliere l’una rispetto all’altra?

Vedi la spiegazione qui .

L’interfaccia Callable è simile a Runnable, in quanto entrambi sono progettati per le classi le cui istanze sono potenzialmente eseguite da un altro thread. Un Runnable, tuttavia, non restituisce un risultato e non può generare un’eccezione controllata.

Quali sono le differenze nelle applicazioni di Runnable e Callable . La differenza è solo con il parametro di ritorno presente in Callable ?

Fondamentalmente, sì. Vedi le risposte a questa domanda . E il javadoc per Callable .

Qual è la necessità di avere entrambi, se Callable può fare tutto ciò che esegue Runnable ?

Perché l’interfaccia Runnable non può fare tutto ciò che Callable fa!

Runnable è disponibile da Java 1.0, ma Callable stato introdotto solo in Java 1.5 … per gestire casi d’uso che Runnable non supporta. In teoria, il team di Java avrebbe potuto cambiare la firma del metodo Runnable.run() , ma ciò avrebbe compromesso la compatibilità binaria con il codice pre-1.5, richiedendo la ricodifica durante la migrazione del vecchio codice Java a JVM più recenti. Questo è un GRANDE NO-NO. Java si sforza di essere retrocompatibile … ed è stato uno dei più grandi punti di vendita di Java per il business computing.

E, ovviamente, ci sono casi d’uso in cui un’attività non ha bisogno di restituire un risultato o lanciare un’eccezione controllata. Per quei casi d’uso, l’uso di Runnable è più conciso rispetto all’utilizzo di Callable e la restituzione di un valore fittizio ( null ) dal metodo call() .

  • Un Callable deve implementare il metodo call() mentre un Runnable deve implementare il metodo run() .
  • Un Callable può restituire un valore ma un Runnable non può.
  • Un Callable può lanciare un’eccezione controllata, ma un Runnable non può.
  • Un Callable può essere usato con i ExecutorService#invokeXXX(Collection< ? extends Callable> tasks) ma un Runnable non può essere.

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

Ho trovato questo in un altro blog che può spiegare un po ‘di più queste differenze :

Sebbene entrambe le interfacce siano implementate dalle classi che desiderano eseguire in un diverso thread di esecuzione, ma ci sono poche differenze tra le due interfacce che sono:

  • Un’istanza Callable restituisce un risultato di tipo V , mentre un’istanza Runnable no.
  • Un’istanza Callable può generare eccezioni controllate, mentre un’istanza Runnable non può

I progettisti di Java sentivano la necessità di estendere le funzionalità dell’interfaccia Runnable , ma non volevano influenzare gli usi dell’interfaccia Runnable e probabilmente quello era il motivo per cui andavano a disporre di un’interfaccia separata denominata Callable in Java 1.5 anziché cambiando il Runnable già esistente.

Diamo un’occhiata a dove si potrebbe usare Runnable e Callable.

Runnable e Callable eseguono entrambi un thread diverso rispetto al thread chiamante. Ma Callable può restituire un valore e Runnable no. Quindi, dove si applica veramente.

Runnable : se hai un incendio e dimentica l’attività, usa Runnable. Inserisci il tuo codice all’interno di Runnable e quando viene chiamato il metodo run (), puoi eseguire il tuo compito. Il thread chiamante in realtà non interessa quando si esegue il tuo compito.

Callable : se si sta tentando di recuperare un valore da un’attività, utilizzare Callable. Ora chiamabile da solo non farà il lavoro. Avrai bisogno di un futuro che ti avvolga attorno a Callable e ottieni i tuoi valori su future.get (). Qui il thread chiamante verrà bloccato fino a quando il futuro ritorna con risultati che a loro volta sono in attesa del metodo call () di Callable da eseguire.

Quindi pensa a un’interfaccia per una class di destinazione in cui hai definito sia i metodi Runnable che Callable. La class chiamante chiamerà in modo casuale i metodi dell’interfaccia non sapendo quale sia eseguibile e quale è Callable. I metodi Runnable verranno eseguiti in modo asincrono, fino a quando viene chiamato un metodo Callable. Qui il thread della class chiamante si bloccherà poiché stai recuperando i valori dalla tua class target.

NOTA: all’interno della class di destinazione è ansible effettuare chiamate a Callable e Runnable su un singolo esecutore di thread, rendendo questo meccanismo simile a una coda di invio seriale. Quindi, fintanto che il chiamante chiama i tuoi metodi Runnable wrapped, il thread chiamante verrà eseguito molto velocemente senza bloccare. Non appena richiama un Callable avvolto nel metodo Future, dovrà bloccare finché tutti gli altri elementi in coda non vengono eseguiti. Solo allora il metodo tornerà con i valori. Questo è un meccanismo di sincronizzazione.

Callable interfaccia Callable dichiara il metodo call() e devi fornire generici come tipo di Object call () dovrebbe restituire –

 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 d’altra parte è l’interfaccia che dichiara il metodo run() che viene chiamato quando si crea una discussione con runnable e call start () su di essa. Puoi anche chiamare direttamente run () ma che esegue solo il metodo run () è lo stesso thread.

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

Per riassumere alcune differenze degne di nota sono

  1. Un object Runnable non restituisce un risultato mentre un object Callable restituisce un risultato.
  2. Un object Runnable non può lanciare un’eccezione controllata dove un object Callable può lanciare un’eccezione.
  3. L’interfaccia Runnable è disponibile da Java 1.0 mentre Callable stato introdotto solo in Java 1.5.

Poche somiglianze includono

  1. Le istanze delle classi che implementano le interfacce Runnable o Callable sono potenzialmente eseguite da un altro thread.
  2. L’istanza di entrambe le interfacce Callable e Runnable può essere eseguita da ExecutorService tramite il metodo submit ().
  3. Entrambe sono interfacce funzionali e possono essere utilizzate nelle espressioni Lambda da Java8.

I metodi nell’interfaccia ExecutorService sono

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

Scopo di queste interfacce dalla documentazione di Oracle:

L’ interfaccia eseguibile dovrebbe essere implementata da qualsiasi class le cui istanze devono essere eseguite da una Thread . La class deve definire un metodo senza argomenti chiamato run .

Callable : un’attività che restituisce un risultato e può generare un’eccezione. Gli implementatori definiscono un singolo metodo senza argomenti chiamati call. L’interfaccia Callable è simile a Runnable , in quanto entrambi sono progettati per le classi le cui istanze sono potenzialmente eseguite da un altro thread. Un Runnable , tuttavia, non restituisce un risultato e non può generare un’eccezione controllata.

Altre differenze:

  1. Puoi passare Runnable per creare una discussione . Ma non puoi creare una nuova discussione passando Callable come parametro. È ansible passare a Callable solo alle istanze di ExecutorService .

    Esempio:

     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 per il fuoco e dimentica le chiamate. Usa Callable per verificare il risultato.

  3. Callable può essere passato al metodo invokeAll a differenza di Runnable . I metodi invokeAny e invokeAll eseguono le forms più comuni di esecuzione di massa, eseguendo una raccolta di attività e quindi aspettando che ne venga completato almeno uno o tutti.

  4. Differenza banale: nome metodo da implementare => run() per Runnable e call() per Callable .

Come già menzionato qui, Callable è un’interfaccia relativamente nuova ed è stata introdotta come parte del pacchetto di concorrenza. Sia Callable che Runnable possono essere usati con esecutori. Thread di class (che implementa Runnable stesso) supporta solo Runnable.

Puoi ancora usare Runnable con executors. Il vantaggio di Callable che è ansible inviarlo a executor e recuperare immediatamente il risultato futuro che verrà aggiornato al termine dell’esecuzione. Lo stesso può essere implementato con Runnable, ma in questo caso devi gestire tu stesso i risultati. Ad esempio, puoi creare una coda di risultati che conserverà tutti i risultati. L’altro thread può attendere questa coda e gestire i risultati che arrivano.

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

I progettisti di Java sentivano la necessità di estendere le funzionalità dell’interfaccia Runnable , ma non volevano influenzare gli usi dell’interfaccia Runnable e probabilmente quello era il motivo per cui andavano a disporre di un’interfaccia separata denominata Callable in Java 1.5 anziché cambiare l’interfaccia Runnable già esistente che faceva parte di Java da Java 1.0. fonte

Le differenze tra Callable e Runnable sono le seguenti:

  1. Callable viene introdotto in JDK 5.0 ma Runnable viene introdotto in JDK 1.0
  2. Callable ha il metodo call () ma Runnable ha il metodo run ().
  3. Callable ha un metodo call che restituisce valore ma Runnable ha un metodo run che non restituisce alcun valore.
  4. il metodo call può generare un’eccezione controllata, ma il metodo run non può generare un’eccezione controllata.
  5. Callable usa il metodo submit () per inserire la coda delle attività, ma Runnable usa il metodo execute () per inserire la coda dei task.

interfaccia pubblica Runnable: l’interfaccia Runnable dovrebbe essere implementata da qualsiasi class le cui istanze devono essere eseguite da un thread. La class deve definire un metodo senza argomenti chiamato run. Questa interfaccia è progettata per fornire un protocollo comune per gli oggetti che desiderano eseguire il codice mentre sono attivi. Ad esempio, Runnable è implementato dalla class Thread. Essere attivi significa semplicemente che un thread è stato avviato e non è stato ancora arrestato.

Inoltre, Runnable fornisce i mezzi affinché una class sia triggers senza sottoclass Thread. Una class che implementa Runnable può essere eseguita senza sottoclassi Thread istanziando un’istanza di Thread e passando se stessa come target. Nella maggior parte dei casi, è consigliabile utilizzare l’interfaccia Runnable se si prevede di sovrascrivere il metodo run () e nessun altro metodo Thread. Questo è importante perché le classi non dovrebbero essere sottoclassate a meno che il programmatore non intenda modificare o migliorare il comportamento fondamentale della class.

Da quando: JDK1.0


interfaccia pubblica Callable :

Un’attività che restituisce un risultato e può generare un’eccezione. Gli implementatori definiscono un singolo metodo senza argomenti chiamati call. L’interfaccia Callable è simile a Runnable, in quanto entrambi sono progettati per le classi le cui istanze sono potenzialmente eseguite da un altro thread. Un Runnable, tuttavia, non restituisce un risultato e non può generare un’eccezione controllata.

La class Executors contiene metodi di utilità per convertire da altri moduli comuni in classi Callable.

Dal: JDK 1.5