Der Unterschied zwischen den Schnittstellen Runnable und Callable in Java

Was ist der Unterschied zwischen der Verwendung der ausführbaren und der abrufbaren Schnittstelle beim Entcasting eines gleichzeitigen Threads in Java? Warum sollten Sie sich für eine andere entscheiden?

Siehe Erklärung hier .

Die Callable-Schnittstelle ist vergleichbar mit Runnable, da beide für classn entworfen sind, deren Instanzen möglicherweise von einem anderen Thread ausgeführt werden. Ein ausführbares Objekt gibt jedoch kein Ergebnis zurück und kann keine geprüfte Ausnahme auslösen.

Was sind die Unterschiede in den Anwendungen von Runnable und Callable . Ist der Unterschied nur mit dem Rückgabewert in Callable ?

Grundsätzlich ja. Siehe die Antworten auf diese Frage . Und das Javadoc für Callable .

Was ist notwendig, wenn Callable alles tun kann, was Callable kann?

Weil die Runnable Schnittstelle nicht alles kann , was Callable tut!

Runnable gibt es seit Java 1.0, aber Callable wurde nur in Java 1.5 eingeführt … um Anwendungsfälle zu behandeln, die Runnable nicht unterstützt. Theoretisch könnte das Java-Team die Signatur der Runnable.run() -Methode geändert haben, aber dies hätte die Binärkompatibilität mit Code vor 1.5 gebrochen, was eine Neucodierung erforderlich macht, wenn alter Java-Code in neuere JVMs migriert wird. Das ist ein großes NO-NO. Java ist bestrebt, abwärtskompatibel zu sein … und das war eines der größten Verkaufsargumente für Business Computing in Java.

Und natürlich gibt es Anwendungsfälle, bei denen eine Aufgabe kein Ergebnis zurückgeben oder eine geprüfte Ausnahme auslösen muss. Für diese Anwendungsfälle ist die Verwendung von Runnable prägnanter als die Verwendung von Callable und die Rückgabe eines Dummy-Werts ( null ) aus der call() -Methode.

  • Ein Callable muss die Methode call() implementieren, während ein Runnable Methode run() implementieren muss.
  • Ein Callable kann einen Wert zurückgeben, ein Runnable jedoch nicht.
  • Ein Callable kann eine geprüfte Ausnahme Runnable aber eine Runnable kann dies nicht.
  • Ein Callable kann mit ExecutorService#invokeXXX(Collection< ? extends Callable> tasks) Methoden verwendet werden, aber eine Runnable kann nicht sein.

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

Ich habe das in einem anderen Blog gefunden, der es ein bisschen mehr erklären kann:

Obwohl beide Schnittstellen von den classn implementiert werden, die in einem anderen Ausführungsthread ausgeführt werden möchten, gibt es jedoch wenige Unterschiede zwischen den beiden Schnittstellen, die sind:

  • Eine Callable gibt ein Ergebnis vom Typ V , eine Runnable Instanz hingegen nicht.
  • Eine Callable kann geprüfte Ausnahmen Runnable , während eine Runnable Instanz dies nicht kann

Die Entwickler von Java hatten das Bedürfnis, die Fähigkeiten der Runnable Schnittstelle zu erweitern, aber sie wollten die Verwendung der Runnable Schnittstelle nicht beeinflussen, und wahrscheinlich war das der Grund, warum sie eine separate Schnittstelle mit dem Namen Callable in Java 1.5 verwenden Callable Ändern des bereits vorhandenen Runnable .

Schauen wir uns an, wo man Runnable und Callable verwenden würde.

Runnable und Callable werden beide auf einem anderen Thread als dem aufrufenden Thread ausgeführt. Callable kann jedoch einen Wert und Runnable nicht ausgeben. Also, wo trifft das wirklich zu?

Runnable : Wenn Sie eine Feuer und vergessen Aufgabe haben, dann verwenden Sie Runnable. Setzen Sie Ihren Code in eine ausführbare Datei und wenn die Methode run () aufgerufen wird, können Sie Ihre Aufgabe ausführen. Der aufrufende Thread kümmert sich wirklich nicht, wenn Sie Ihre Aufgabe ausführen.

Callable : Wenn Sie versuchen, einen Wert von einer Aufgabe abzurufen, verwenden Sie Callable. Jetzt allein aufrufbar, wird die Aufgabe nicht erfüllen. Sie werden eine Zukunft benötigen, die Sie um Ihre Callable wickeln und Ihre Werte auf future.get () erhalten. Hier wird der aufrufende Thread blockiert, bis das Future mit Ergebnissen zurückkommt, die darauf warten, dass Calles Call () -Methode ausgeführt wird.

Denken Sie also über eine Schnittstelle zu einer Zielklasse nach, in der Sie sowohl die implementierbaren als auch die ausführbaren Methoden “Runnable” und “Callable” definiert haben. Die aufrufende class ruft zufällig Ihre Schnittstellenmethoden auf, ohne zu wissen, welche Runnable und welche Callable ist. Die Runnable-Methoden werden asynchron ausgeführt, bis eine Callable-Methode aufgerufen wird. Hier wird der Thread der aufrufenden class blockiert, da Sie Werte aus Ihrer Zielklasse abrufen.

HINWEIS: Innerhalb Ihrer Zielklasse können Sie Aufrufe an Callable und Runnable für einen einzelnen Thread-Executor ausführen, wodurch dieser Mechanismus einer seriellen Dispatch-Warteschlange ähnelt. Solange der Aufrufer Ihre Runable-Methode aufruft, wird der aufrufende Thread sehr schnell ausgeführt, ohne zu blockieren. Sobald eine Callable in Future-Methode aufgerufen wird, muss sie blockiert werden, bis alle anderen in der Warteschlange befindlichen Elemente ausgeführt wurden. Nur dann wird die Methode mit Werten zurückkehren. Dies ist ein Synchronisationsmechanismus.

Callable Interface deklariert call() Methode call() und Sie müssen Generics als Callable call () sollte zurückgeben –

 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 dagegen ist eine Schnittstelle, die run() -Methode deklariert, die aufgerufen wird, wenn Sie einen Thread mit dem runnable erstellen und start () aufrufen. Sie können auch run () direkt aufrufen, aber die run () -Methode führt nur denselben Thread aus.

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

Zusammenfassend einige bemerkenswerte Unterschiede sind

  1. Ein Runnable Objekt gibt kein Ergebnis zurück, während ein Callable Objekt ein Ergebnis zurückgibt.
  2. Ein Runnable Objekt kann keine geprüfte Ausnahme auslösen, während ein Callable Objekt eine Ausnahme Callable kann.
  3. Die Runnable Schnittstelle ist seit Java 1.0 Callable wohingegen Callable nur in Java 1.5 eingeführt wurde.

Wenige Ähnlichkeiten schließen ein

  1. Instanzen der classn, die Runnable- oder Callable-Schnittstellen implementieren, werden möglicherweise von einem anderen Thread ausgeführt.
  2. Die Instanz der Callable- und Runnable-Schnittstellen kann von ExecutorService über die Methode submit () ausgeführt werden.
  3. Beide sind funktionale Schnittstellen und können seit Java8 in Lambda-Ausdrücken verwendet werden.

Methoden in der ExecutorService-Schnittstelle sind

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

Zweck dieser Schnittstellen aus der Oracle-Dokumentation:

Die ausführbare Schnittstelle sollte von jeder class implementiert werden, deren Instanzen von einem Thread ausgeführt werden sollen. Die class muss eine Methode ohne Argumente namens run .

Callable : Eine Task, die ein Ergebnis zurückgibt und eine Ausnahme auslösen kann. Implementoren definieren eine einzige Methode ohne Argumente namens call. Die Callable Schnittstelle ist vergleichbar mit Runnable , da beide für classn entworfen sind, deren Instanzen möglicherweise von einem anderen Thread ausgeführt werden. Ein Runnable gibt jedoch kein Ergebnis zurück und kann keine geprüfte Ausnahme Runnable .

Andere Unterschiede:

  1. Sie können Runnable , um einen Thread zu erstellen. Sie können jedoch keinen neuen Thread erstellen, indem Sie Callable als Parameter übergeben. Sie können Callable nur an ExecutorService Instanzen übergeben.

    Beispiel:

     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. Verwenden Sie Runnable für Feuer und vergessen Sie Anrufe. Verwenden Sie Callable , um das Ergebnis zu überprüfen.

  3. Callable kann im Gegensatz zu Runnable an die invokeAll- Methode Runnable . Die Methoden invokeAny und invokeAll führen die am häufigsten verwendeten Formen der invokeAll , indem sie eine Sammlung von Aufgaben ausführen und dann auf mindestens einen oder alle warten, um abzuschließen

  4. Trivialer Unterschied: zu implementierender Methodenname => run() für Runnable und call() für Callable .

Wie bereits erwähnt, ist Callable eine relativ neue Schnittstelle und wurde als Teil des Parallelitätspakets eingeführt. Sowohl Callable als auch Runnable können mit Executoren verwendet werden. classn-Thread (der Runnable selbst implementiert) unterstützt nur Runnable.

Sie können Runnable weiterhin mit Executoren verwenden. Der Vorteil von Callable, dass Sie es an den Executor senden und sofort zurück erhalten können. Das zukünftige Ergebnis wird aktualisiert, wenn die Ausführung beendet ist. Das Gleiche kann mit Runnable implementiert werden, aber in diesem Fall müssen Sie die Ergebnisse selbst verwalten. Zum Beispiel können Sie eine Ergebniswarteschlange erstellen, die alle Ergebnisse enthält. Ein anderer Thread kann auf diese Warteschlange warten und sich mit den Ergebnissen befassen, die ankommen.

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

Die Entwickler von Java hatten das Bedürfnis, die Fähigkeiten der Runnable Schnittstelle zu erweitern, aber sie wollten die Verwendung der Runnable Schnittstelle nicht beeinflussen, und wahrscheinlich war das der Grund, warum sie eine separate Schnittstelle mit dem Namen Callable in Java 1.5 verwenden Callable Ändern der bereits vorhandenen Runnable Schnittstelle, die seit Java 1.0 Teil von Java ist. Quelle

Der Unterschied zwischen Callable und Runnable ist folgender:

  1. Callable wird in JDK 5.0 eingeführt, Runnable wird jedoch in JDK 1.0 eingeführt
  2. Callable hat call () -Methode, aber Runnable hat run () -Methode.
  3. Callable hat eine Aufrufmethode, die einen Wert zurückgibt, aber Runnable hat eine Methode ausgeführt, die keinen Wert zurückgibt.
  4. call-Methode kann checked exception auslösen, aber run method kann checked exception nicht auslösen.
  5. Aufrufbare Verwendung submit () -Methode, um in die Aufgabenwarteschlange einzufügen, aber Runnable verwendet execute () -Methode, um sie in die Aufgabenwarteschlange einzufügen.

Öffentliche Schnittstelle Runnable: Die Runnable-Schnittstelle sollte von jeder class implementiert werden, deren Instanzen von einem Thread ausgeführt werden sollen. Die class muss eine Methode ohne Argumente namens run definieren. Diese Schnittstelle soll ein gemeinsames Protokoll für Objekte bereitstellen, die Code ausführen möchten, während sie aktiv sind. Zum Beispiel wird Runnable von der class Thread implementiert. Aktiv sein bedeutet einfach, dass ein Thread gestartet wurde und noch nicht gestoppt wurde.

Darüber hinaus bietet Runnable die Möglichkeit, dass eine class aktiv ist, während Thread nicht unterklassifiziert wird. Eine class, die Runnable implementiert, kann ohne Unterklassen-Thread ausgeführt werden, indem eine Thread-Instanz instanziiert und als Ziel übergeben wird. In den meisten Fällen sollte die Runnable-Schnittstelle verwendet werden, wenn Sie nur die Methode run () und keine anderen Thread-Methoden überschreiben möchten. Dies ist wichtig, weil classn nicht unterklassifiziert werden sollten, außer der Programmierer beabsichtigt, das grundlegende Verhalten der class zu modifizieren oder zu verbessern.

Seit: JDK1.0


öffentliche Schnittstelle Callable :

Eine Aufgabe, die ein Ergebnis zurückgibt und eine Ausnahme auslösen kann. Implementoren definieren eine einzige Methode ohne Argumente namens call. Die Callable-Schnittstelle ist vergleichbar mit Runnable, da beide für classn entworfen sind, deren Instanzen möglicherweise von einem anderen Thread ausgeführt werden. Ein ausführbares Objekt gibt jedoch kein Ergebnis zurück und kann keine geprüfte Ausnahme auslösen.

Die Executors-class enthält Hilfsmethoden zum Konvertieren von anderen allgemeinen Formularen in Callable-classn.

Seit: JDK 1.5