5 votes

Comment annuler un ExecutorService en java

J'ai écrit une application qui exécute certains threads en utilisant ExecutorService et attend qu'ils finissent comme ceci :

ExecutorService exService;
exService = Executors.newCachedThreadPool();
exService.execute(T1);
exService.execute(T2);
exService.shutdown();
boolean finshed = exService.awaitTermination(5, TimeUnit.MINUTES);

parfois j'ai besoin d'annuler l'exécution de ces threads (l'ensemble de la ExecutorService ).
J'ai essayé exService.shutdownNow() mais il jette java.lang.InterruptedException et n'annule pas les fils.
Comment puis-je annuler l'exécution de ces threads ?


EDIT : code de classe T1 ajouté à la demande de nanda

public class TC implements Runnable{
    private ExtractedDataBuffer Buffer;
    private Scraper scraper;
    private String AppPath;
    private boolean Succeed=false;
    private Map<String,Object> Result=null;
    private JLabel StatElement;

    public TC(ExtractedDataBuffer Buffer,String AppPath,String XMLfile,JLabel Stat) throws FileNotFoundException {
        this.Buffer = Buffer;
        this.AppPath=AppPath;
        this.StatElement=Stat;

        ScraperConfiguration config;
        config = new ScraperConfiguration(AppPath + Main.XMLFilesPath +XMLfile);
        scraper = new Scraper(config, AppPath);
    }

    private void extract(){
        try{
            mainF.SetIconStat("working", this.StatElement);
            scraper.execute();
            if(scraper.getStatus()==Scraper.STATUS_FINISHED){
                this.Succeed=true;
                Map<String,Object> tmp=new HashMap<String,Object>();
                tmp.put("UpdateTime", ((Variable) scraper.getContext().get("UpdateTime")).toString().trim());
                Buffer.setVal(this.Result);
                mainF.SetIconStat("done", this.StatElement);
            }else{
                this.Succeed=false;
                this.Result=null;
                Buffer.setVal(null);
                mainF.SetIconStat("error", this.StatElement);
            }
        }catch(Exception ex){
            this.Succeed=false;
            this.Result=null;
            Buffer.setVal(null);
            mainF.SetIconStat("error", this.StatElement);
        }
    }

    public void run() {
        this.extract();
    }    
}

5voto

nanda Points 12764

Si vous remplacez shutdown() par shutdownNow(), vous faites la bonne chose dans le code que vous avez écrit. Mais alors, vérifiez la documentation de shutdownNow() :

Il n'y a pas de garantie au-delà des efforts déployés pour arrêter le traitement. des tâches en cours d'exécution. Par exemple, les implémentations typiques par Thread.interrupt(), de sorte que toute tâche qui ne répond pas aux interruptions interruptions peut ne jamais se terminer.

Il est donc probable que vos T1 et T2 ne sont pas codés de manière correcte et ne répondent pas assez bien à l'interruption. Pouvez-vous peut-être copier le code pour eux ?

--

Sur la base de votre code, je suppose que le code qui prend beaucoup de temps est scraper.execute(), n'est-ce pas ? Donc, à l'intérieur de ces méthodes, vous devez constamment vérifier quelque chose comme ceci :

if (Thread.interrupted()) {
   throw new InterruptedException();
}

Si l'interruption survient, l'exception InterruptedException sera levée et capturée dans votre déclaration catch et le thread s'arrêtera.

4voto

Ingo Kegel Points 13858

Mon problème avec Future#cancel() est que les appels ultérieurs à get() lancer un CancellationException . Parfois, je veux encore pouvoir appeler get() sur le Future afin de récupérer un résultat partiel après l'arrêt du service exécuteur. Dans ce cas, il est possible d'implémenter la logique d'arrêt dans les appelables que vous soumettez au service exécuteur. Utilisez un champ comme

private volatile boolean terminate;

public void terminate() {
    terminate = true;
}

et vérifier si terminate dans l'appelant aussi souvent que nécessaire. En outre, vous devez vous souvenir de vos callables quelque part pour pouvoir appeler terminate() sur toutes ces personnes.

2voto

tolitius Points 9816

Utilisez l'exécuteur. soumettre elle étend la méthode de base Executor.execute(java.lang.Runnable) en créant et en renvoyant une méthode de type Future qui peuvent être utilisés pour annuler l'exécution et/ou attendre l'achèvement :

task = Executor.submit( T1 )
...
task.cancel( true )

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X