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?

War es hilfreich?

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 und Callable. Ist der Unterschied nur mit dem Rückgabeparameter in Callable?

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, was Runnable 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 muss call() Verfahren implementieren, während ein Runnable run() Verfahren implementieren muss.
  • A Callable kann einen Wert zurückgeben, sondern ein Runnable kann es nicht.
  • A Callable kann Ausnahme werfen geprüft, aber eine Runnable nicht.
  • Ein Callable kann mit ExecutorService#invokeXXX(Collection<? extends Callable<T>> tasks) Methoden verwendet werden, aber ein Runnable 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 Typ V, während eine Runnable Instanz nicht.
  • A Callable<V> Instanz Ausnahmen geprüft werfen kann, während eine Runnable 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

  1. Ein Runnable Objekt liefert kein Ergebnis, während ein Callable Objekt ein Ergebnis zurückgibt.
  2. Ein Runnable Objekt kann nicht eine geprüfte Ausnahme werfen wheras ein Callable Objekt kann ein Wurf Ausnahme.
  3. Die Runnable Schnittstelle gibt es schon seit Java 1.0 während Callable nur eingeführt in Java 1.5.

Ein paar Ähnlichkeiten umfassen

  1. Instanzen der Klassen, die Runnable oder aufrufbare Schnittstellen implementieren sind potentiell von einem anderen Thread ausgeführt wird.
  2. Instanz beiden Callable und Runnable-Schnittstellen kann durch ExecutorService ausgeführt wird via einreichen () -Methode.
  3. 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:

  1. Sie können Runnable passieren eine Thread . Aber Sie können nicht neue Themen erstellen, indem Callable als Parameter übergeben. Sie können aufrufbare passieren nur ExecutorService Instanzen.

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

  3. Callable kann auf invokeAll Methode im Gegensatz zu Runnable. Methoden invokeAny und invokeAll 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

  4. Trivial Unterschied: Methodennamen umgesetzt werden => run() für Runnable und call() für Callable

  5. .

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:

  1. Callable wird in JDK eingeführt 5.0 aber Runnable wird in JDK 1.0
  2. eingeführt
  3. Callable call () Methode hat aber Runnable ausgeführt wird () -Methode.
  4. Callable hat Call-Methode, die Wert zurückgibt, aber Runnable hat Methode ausgeführt, die keinen Wert zurückgibt.
  5. Call-Methode kann geprüft Ausnahme werfen, aber laufen Methode nicht Ausnahme werfen geprüft werden.
  6. 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();
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top