Der Unterschied zwischen der Runnable und Callable-Schnittstellen in Java
-
02-07-2019 - |
Frage
Was ist der Unterschied besteht darin, die Runnable
und Callable
Schnittstellen zwischen der Verwendung, wenn ein gleichzeitigen Thread in Java entwerfen, warum sollten Sie einen über die andere wählen?
Lösung
Siehe Erläuterung hier .
Die aufrufbare Schnittstelle ist ähnlich Runnable, daß beide sind so ausgelegt, für die Klassen, deren Instanzen möglicherweise von einem anderen ausgeführt Faden. A Runnable, tut jedoch nicht ein Ergebnis zurück und kann eine nicht werfen Ausnahme geprüft.
Andere Tipps
Was sind die Unterschiede in den Anwendungen von
Runnable
undCallable
. Ist der Unterschied nur mit dem Rückgabeparameter inCallable
?
Grundsätzlich ja. Siehe die Antworten auf diese Frage . Und die javadoc für Callable
.
Was ist die Notwendigkeit, die sowohl wenn
Callable
kann alles, wasRunnable
tun tut?
Da der Runnable
Schnittstelle kann nicht tun alles, was Callable
tut!
Runnable
gibt es seit Java 1.0, aber Callable
nur in Java 1.5 eingeführt wurde ... Anwendungsfälle zu behandeln, die nicht unterstützt Runnable
. Theoretisch könnte das Java-Team die Unterschrift der Runnable.run()
Methode geändert, aber die binäre Kompatibilität mit bereits 1,5 Code gebrochen hätte, Umkodierung erforderlich ist, wenn alten Java-Code JVMs auf neueren migrieren. Das ist ein großer No-No. Java ist bestrebt, rückwärtskompatibel zu sein ... und das ist eine der Java größten Verkaufsargumente für Business-Computing gewesen.
Und natürlich gibt es Anwendungsfälle, wo eine Aufgabe nicht der Fall ist Notwendigkeit ein Ergebnis zurückzukehren oder eine geprüfte Ausnahme werfen. Für diejenigen Anwendungsfälle, Runnable
Verwendung ist prägnanter als Callable<Void>
und unter Verwendung eines Dummy (null
) Wert aus der call()
Verfahren zurückkehrt.
- A
Callable
musscall()
Verfahren implementieren, während einRunnable
run()
Verfahren implementieren muss. - A
Callable
kann einen Wert zurückgeben, sondern einRunnable
kann es nicht. - A
Callable
kann Ausnahme werfen geprüft, aber eineRunnable
nicht. -
Ein
Callable
kann mitExecutorService#invokeXXX(Collection<? extends Callable<T>> tasks)
Methoden verwendet werden, aber einRunnable
kann nicht sein.public interface Runnable { void run(); } public interface Callable<V> { V call() throws Exception; }
Ich fand diese in einem anderen Blog, dass es ein bisschen mehr diese Unterschiede :
Obwohl beide die Schnittstellen von den Klassen implementiert werden, die in einem anderen Thread der Ausführung ausführen möchten, aber es gibt einige Unterschiede zwischen den beiden Schnittstelle, die sind:
- A
Callable<V>
Instanz gibt ein Ergebnis vom TypV
, während eineRunnable
Instanz nicht. - A
Callable<V>
Instanz Ausnahmen geprüft werfen kann, während eineRunnable
Instanz kann nicht
Die Designer von Java haben das Bedürfnis, der die Fähigkeiten des Runnable
Schnittstelle erstreckt, aber sie wollten nicht die Verwendungen der Runnable
Schnittstelle beeinflussen und wahrscheinlich das war der Grund, warum sie gingen eine separate Schnittstelle namens Callable
für mit in Java 1.5 als die bereits bestehenden Runnable
ändern.
Lassen Sie uns an, wo man Runnable und Callable verwenden würde.
Runnable und Callable beide laufen auf einem anderen Thread als dem aufrufenden Thread. Aber aufrufbare kann einen Wert zurückgeben und Runnable kann es nicht. Also, wo dies wirklich gilt.
Runnable : Wenn Sie ein Feuer und vergessen Aufgabe haben, dann Runnable verwenden. Setzen Sie Ihren Code in einem Runnable und wenn die Methode run () aufgerufen wird, können Sie Ihre Aufgabe ausführen. Der aufrufende Thread wirklich kümmert sich nicht darum, wenn Sie Ihre Aufgabe ausführen.
Callable : Wenn Sie einen Wert aus einer Aufgabe abzurufen versuchen, dann Callable verwenden. Jetzt aufrufbar auf seinem eigenen wird den Job nicht machen. Sie erhalten eine Zukunft benötigen, die Sie um Ihre aufrufbare wickeln und Ihre Werte auf future.get get (). Hier ist der Aufruf Thread blockiert wird, bis die Zukunft mit Ergebnissen kommt zurück, das wiederum für aufrufbare des Anklopf () -Methode auszuführen.
denken also über eine Schnittstelle zu einem Zielklasse, wo Sie beide Runnable haben und Callable gewickelte Methoden definiert. Die aufrufende Klasse wird nach dem Zufall Ihre Schnittstelle Methoden aufrufen, ohne zu wissen, welche Runnable ist und das ist aufrufbare. Die Runnable Methoden ausführen werden asynchron, bis eine Callable-Methode aufgerufen wird. Hier die Thread der anrufenden Klasse blockiert, da Sie Werte aus Ihrem Ziel Klasse abrufen.
Hinweis: In Ihrer Zielklasse Sie die Anrufe Callable und Runnable auf einem einzigen Thread Testamentsvollstrecker machen können, so dass dieser Mechanismus ähnlich eine serielle Absende-Warteschlange. Solange der Anrufer ruft Ihre Runnable gewickelte Methoden der aufrufende Thread werden wirklich schnell ausführen, ohne zu blockieren. Sobald es eine aufrufbare in Zukunft Methode gewickeltes anruft, wird es haben zu blockieren, bis alle andere Warteschlangen Elemente ausgeführt werden. Erst dann wird das Verfahren mit Werten zurück. Dies ist ein Synchronisationsmechanismus.
Callable
Schnittstelle deklariert call()
Methode und Sie müssen Generika als Art von Objekt aufrufen, um () zurückkehren sollte -
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
auf der anderen Seite ist die Schnittstelle run()
Methode deklariert, die aufgerufen wird, wenn Sie einen Thread mit dem runnable erstellen und rufen Sie () auf starten. Sie können auch anrufen run () direkt, aber das führt nur die Methode run () ist selber Thread.
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();
}
Zusammenfassend einige bemerkenswerte Unterschied sind
- Ein
Runnable
Objekt liefert kein Ergebnis, während einCallable
Objekt ein Ergebnis zurückgibt. - Ein
Runnable
Objekt kann nicht eine geprüfte Ausnahme werfen wheras einCallable
Objekt kann ein Wurf Ausnahme. - Die
Runnable
Schnittstelle gibt es schon seit Java 1.0 währendCallable
nur eingeführt in Java 1.5.
Ein paar Ähnlichkeiten umfassen
- Instanzen der Klassen, die Runnable oder aufrufbare Schnittstellen implementieren sind potentiell von einem anderen Thread ausgeführt wird.
- Instanz beiden Callable und Runnable-Schnittstellen kann durch ExecutorService ausgeführt wird via einreichen () -Methode.
- Beide sind funktionale Schnittstellen und können in Lambda-Ausdrücke seit Java8 verwendet werden.
Methoden in ExecutorService Schnittstelle sind
<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
<T> Future<T> submit(Runnable task, T result);
Zweck dieser Schnittstellen von Oracle-Dokumentation:
Runnable Schnittstelle implementiert werden sollte von jeder Klasse, deren Instanzen bestimmt durch einen Thread
ausgeführt werden. Die Klasse muss ein Verfahren ohne Argumente definiert genannt run
.
aufrufbare : A Aufgabe, die ein Ergebnis zurückgibt und eine Ausnahme werfen könnte. Implementierer definieren eine einzelne Methode ohne Aufruf Argumente genannt.
Die Callable
Schnittstelle ähnelt Runnable
, daß sowohl für die Klassen bestimmt sind, deren Instanzen potentiell von einem anderen Thread ausgeführt. Ein Runnable
jedoch kein Ergebnis zurück und kann nicht eine geprüfte Ausnahme werfen.
Weitere Unterschiede:
-
Sie können
Runnable
passieren eine Thread . Aber Sie können nicht neue Themen erstellen, indemCallable
als Parameter übergeben. Sie können aufrufbare passieren nurExecutorService
Instanzen.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(); } }
-
Mit
Runnable
für Feuer und vergessen Anrufe. Verwenden SieCallable
um das Ergebnis zu überprüfen. -
Callable
kann auf invokeAll Methode im Gegensatz zuRunnable
. MethodeninvokeAny
undinvokeAll
die am häufigsten nützlichen Formen von Massen Ausführung auszuführen, eine Sammlung von Aufgaben ausführen und dann für mindestens eine warten, oder alle, zu vervollständigen -
Trivial Unterschied: Methodennamen umgesetzt werden =>
run()
fürRunnable
undcall()
fürCallable
.
Wie bereits erwähnt wurde hier Callable ist relativ neue Schnittstelle und es wurde als Teil des gemeinsamen Zugriffs-Pakets eingeführt. Sowohl Callable und Runnable mit Testamentsvollstrecker eingesetzt werden. Klasse Thread (die implementiert Runnable selbst) unterstützt Runnable nur.
Sie können nach wie vor Runnable verwenden mit Vollstrecker. Der Vorteil von Callable, dass Sie es senden können Executor und sofort Zukunft Ergebnis zurück, die aktualisiert werden, 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 die Ergebnisse Warteschlange erstellen, die alle Ergebnisse halten wird. Andere Gewinde auf dieser Warteschlange warten können und mit den Ergebnissen befassen, die ankommen.
+-------------------------------------+--------------------------------------------------------------------------------------------------+
| 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 |
+-------------------------------------+--------------------------------------------------------------------------------------------------+
Die Designer von Java haben das Bedürfnis, der die Fähigkeiten des Runnable
Schnittstelle erstreckt, aber sie wollten nicht die Verwendungen der Runnable
Schnittstelle beeinflussen und wahrscheinlich das war der Grund, warum sie gingen eine separate Schnittstelle namens Callable
für mit in Java 1.5 als die bereits bestehende Runnable
Schnittstelle zu ändern, die ein Teil von Java seit Java 1.0 wurden. Quelle
Der Unterschied zwischen Callable und Runnable sind folgende:
- Callable wird in JDK eingeführt 5.0 aber Runnable wird in JDK 1.0 eingeführt
- Callable call () Methode hat aber Runnable ausgeführt wird () -Methode.
- Callable hat Call-Methode, die Wert zurückgibt, aber Runnable hat Methode ausgeführt, die keinen Wert zurückgibt.
- Call-Methode kann geprüft Ausnahme werfen, aber laufen Methode nicht Ausnahme werfen geprüft werden.
- aufrufbare Verwendung einreichen () -Methode in Task-Warteschlange gestellt, aber Runnable Verwendung execute () -Methode in der Task-Warteschlange zu stellen.
aufrufbare und Runnable beide sind ähnlich zueinander und bei der Umsetzung des Thread nutzen kann. Im Falle der Umsetzung Runnable Sie müssen run () Methode, aber bei aufrufbar implementieren müssen Sie implementieren müssen call () Methode, beide Verfahren Arbeiten in ähnlicher Weise aber aufrufbar call () Methode haben mehr flexibility.There einige Unterschiede zwischen ihnen.
Der Unterschied zwischen Runnable und aufrufbar als below--
1) Die run () Methode von runnable Rückgabe void , bedeutet, wenn Sie Ihren Faden Rückkehr etwas wollen, die Sie dann weiter verwenden können Sie haben keine andere Wahl, mit Runnable run () Methode. Es gibt eine Lösung 'Callable' , wenn Sie irgendeine Sache in Form von zurückkehren möchten Objekt dann Sie sollte statt Runnable verwenden Callable . Aufrufbare Schnittstelle hat Methode 'call ()', das Objekt zurück .
Methodensignatur - Runnable->
public void run(){}
Callable->
public Object call(){}
2) Bei Runnable run () Methode, wenn eine geprüfte Ausnahme ergibt sich dann müssen Sie Notwendigkeit, mit Try-Catch-Block behandelt , aber im Falle von aufrufbar call () Verfahren Sie kann kontrolliert Ausnahme auslösen , wie unten
public Object call() throws Exception {}
3) Runnable kommt aus Legacy Java 1.0 Version, aber aufrufbar kam in Java 1.5 Version mit < strong> Executer Rahmen.
Wenn Sie sind vertraut mit Vollstrecker , dann sollten Sie verwenden aufrufbare statt Runnable .
Ich hoffe, Sie verstehen.
Runnable (vs) Callable kommt in Punkt, wenn wir Executer Rahmen verwenden.
ExecutorService ist ein Subschnittstelle von Executor
, die beide Runnable und Callable Aufgaben übernimmt.
Frühere Multi-Threading kann Schnittstelle erreicht wird mit Runnable
Seit 1.0 , aber hier ist das Problem nach der Thread Aufgabe zu erledigen sind wir nicht in der Lage die Themen Informationen zu sammeln. In Ordnung, die Daten sammeln wir Statische Felder verwenden.
Beispiel separate Threads jeden Schüler Daten zu sammeln.
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() );
}
Um dieses Problem zu lösen, sie eingeführt haben, Callable<V>
Seit 1.5 , die ein Ergebnis zurückgibt und eine Ausnahme werfen könnte.
-
Single abstrakte Methode : Sowohl Callable und Runnable Schnittstelle hat eine einzige abstrakte Methode, was bedeutet, können sie in Lambda-Ausdrücke in Java 8 verwendet werden
.public interface Runnable { public void run(); } public interface Callable<Object> { public Object call() throws Exception; }
Es gibt ein paar verschiedene Möglichkeiten zu delegieren Aufgaben zur Ausführung an eine ExecutorService .
-
execute(Runnable task):void
Kisten neuer Thread aber nicht blockiert Hauptthread oder Anrufer Thread wie diese Methode Rückkehr ungültig. -
submit(Callable<?>):Future<?>
,submit(Runnable):Future<?>
Kisten neuer Thread und blockiert Haupt-Thread, wenn Sie mit future.get () .
Beispiel der Verwendung von Interfaces Runnable, aufrufbare mit Executor Rahmen.
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();
}
}