différence entre exécuteur testamentaire.soumettre et exécuteur testamentaire.exécuter dans ce code en Java?

j'apprends à utiliser exectorServices pour regrouper threads et envoyer des tâches. J'ai un programme simple en dessous de

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


class Processor implements Runnable {

    private int id;

    public Processor(int id) {
        this.id = id;
    }

    public void run() {
        System.out.println("Starting: " + id);

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            System.out.println("sorry, being interupted, good bye!");
            System.out.println("Interrupted "+Thread.currentThread().getName());
            e.printStackTrace();    
        }

        System.out.println("Completed: " + id);
    }
}


public class ExecutorExample {

    public static void main(String[] args) {
        Boolean isCompleted=false;

        ExecutorService executor = Executors.newFixedThreadPool(2);

        for(int i=0; i<5; i++) {
            executor.execute(new Processor(i));
        }

        //executor does not accept any more tasks but the submitted tasks continue
        executor.shutdown();

        System.out.println("All tasks submitted.");

        try {
            //wait for the exectutor to terminate normally, which will return true
            //if timeout happens, returns false, but this does NOT interrupt the threads
            isCompleted=executor.awaitTermination(100, TimeUnit.SECONDS);
            //this will interrupt thread it manages. catch the interrupted exception in the threads 
            //If not, threads will run forever and executor will never be able to shutdown.
            executor.shutdownNow();
        } catch (InterruptedException e) {
        }

        if (isCompleted){
        System.out.println("All tasks completed.");
       }
        else {
            System.out.println("Timeout "+Thread.currentThread().getName());
        }
    }
        }

il ne fait rien de fantaisiste, mais crée deux threads et soumet 5 tâches au total. Après chaque thread complète sa tâche, il prend le suivant, Dans le code ci-dessus, j'utilise executor.submit . J'ai aussi changé en executor.execute . Mais je ne vois aucune différence dans la sortie. En quoi les submit and execute méthodes différentes? Ce qu' le API dit

Méthode de soumettre s'étend de la base de la méthode de l'Exécuteur testamentaire.execute (java.lang.Runnable) en créant et retournant un futur qui peut être utilisé pour annuler l'exécution et/ou attendre l'achèvement. Méthodes invokeAny et invokeAll exécutent les formes les plus couramment utiles d'exécution en vrac, en exécutant un ensemble de tâches et en attendant au moins un, ou tous, à compléter. (Class Executorcompleletionservice peut être utilisé pour écrire des variantes personnalisées de ces méthodes.)

mais ce n'est pas clair pour moi ce que cela signifie exactement? Merci

33
demandé sur Hovercraft Full Of Eels 2013-09-11 03:22:14

5 réponses

comme vous le voyez de la JavaDoc execute(Runnable) ne renvoie rien.

cependant, submit(Callable<T>) renvoie un objet Future qui vous permet d'annuler programmatiquement le thread plus tard ainsi que d'obtenir le T qui est retourné lorsque le Callable est terminé. Voir JavaDoc du futur pour plus de détails

Future<?> future = executor.submit(longRunningJob);
...
//long running job is taking too long
future.cancel(true);

de plus, si future.get() == null et ne jette aucune exception alors Exécutable exécuté avec succès

33
répondu dkatzel 2015-03-12 11:18:35

la différence est que execute commence simplement la tâche sans plus attendre, alors que submit renvoie un objet Future pour gérer la tâche. Vous pouvez faire les choses suivantes avec l'objet Future :"

  • annuler la tâche prématurément, avec la méthode cancel .
  • attendre la fin de la tâche d'exécution, avec get .

l'interface Future est plus utile si vous soumettez une Callable à la piscine. La valeur de retour de la méthode call sera retournée lorsque vous appellerez Future.get . Si vous ne maintenez pas une référence au Future , il n'y a pas de différence.

37
répondu tbodt 2013-09-10 23:31:38

execute: l'Utiliser pour le feu et oublier appelle

submit: l'Utiliser pour inspecter le résultat de l'appel de méthode et de prendre des mesures appropriées Future opposé retourné par l'appel

différence majeure: Exception manipulation

submit() se cache Non manipulé Exception dans le cadre lui-même.

execute() lancers un-handled Exception .

Solution pour le traitement des Exceptions avec submit()

  1. enveloppez votre Callable or Runnable code in try{} catch{} block

    ou

  2. Garder future.get() call in try{} catch{} block

    ou

  3. mettre en place votre propre ThreadPoolExecutor et remplacer afterExecute méthode

concernant la visite d'autres questions sur

invokeAll :

exécute les tâches données, en retournant une liste de Futures détenant leur statut et les résultats lorsque tout terminé ou le délai expire, selon ce qui se produit en premier.

invokeAny :

exécute les tâches données, en retournant le résultat d'un qui a complété avec succès (c. - à-d., sans lancer une exception), s'il y a faire avant l'expiration du délai donné.

utilisez invokeAll si vous voulez attendre que toutes les tâches soumises à compléter.

utilisez invokeAny si vous recherchez l'exécution réussie d'une tâche sur N tâches soumises. Dans ce cas, les tâches en cours seront annulées si l'une d'entre elles est accomplie avec succès.

POSTE Associé Avec exemple de code:

Choisir entre ExecutorService de soumettre et ExecutorService execute

8
répondu Ravindra babu 2017-10-02 05:55:53

soumettre-renvoie L'objet futur, qui peut être utilisé pour vérifier le résultat de la tâche soumise. Peut être utilisé pour annuler ou pour vérifier isDone etc.

Exécuter - ne retourne rien.

4
répondu Preetham R U 2015-07-08 12:47:36

essentiellement les deux appels exécutent,si vous voulez un objet futur vous devez appeler la méthode submit() ici du doc

public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
}


public <T> Future<T> submit(Runnable task, T result) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task, result);
    execute(ftask);
    return ftask;
}

comme vous pouvez le voir java n'a vraiment aucun moyen de démarrer un thread autre que d'appeler la méthode run (), IMO. puisque j'ai également trouvé que Callable.call() méthode est appelé à l'intérieur run() méthode. par conséquent, si l'objet est appelable, il appellerait encore la méthode run() , qui appellerait la méthode call() . de doc.

public void run() {
    if (state != NEW ||
        !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                     null, Thread.currentThread()))
        return;
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                setException(ex);
            }
            if (ran)
                set(result);
        }
    } finally {
        // runner must be non-null until state is settled to
        // prevent concurrent calls to run()
        runner = null;
        // state must be re-read after nulling runner to prevent
        // leaked interrupts
        int s = state;
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}
0
répondu amarnath harish 2018-07-06 11:33:20