Question

J'ai une longue tâche en cours d'exécution, quelque chose comme:

public void myCancellableTask() {
    while ( someCondition ) {
       checkIfCancelRequested();
       doSomeWork();
    }
 }

La tâche peut être annulée (un cancel est demandée et checkIfCancelRequested () vérifie l'annulation du pavillon). En général, quand j'écris boucles résiliables comme ça, j'utilise un drapeau pour indiquer qu'une annulation a été demandée. Mais, je sais que je pourrais utiliser aussi Thread.interrupt et vérifier si le fil a été interrompue. Je ne sais pas ce qui serait l'approche préférée et pourquoi, pensées?

merci,

Jeff

Était-ce utile?

La solution

Interrompre soufflera le fil sur une liste des conditions d'attente spécifiées. Votre drapeau ne sera pas annuler. Si vous souhaitez interrompre attend sur IO et les événements, utilisez interruption. Sinon, utilisez votre propre.

Autres conseils

Un problème avec l'utilisation d'interruption est que si vous ne contrôlez pas tout le code en cours d'exécution , vous courez le risque de l'interruption ne fonctionne pas « correctement » en raison de quelqu'un d'autre compréhension brisée de la façon dont pour gérer les interruptions dans leur bibliothèque. C'est l'API invisiblement exporte une API autour de sa manipulation de interrupts que vous deveniez dépendant.

Dans votre exemple, doSomeWork était dans un supposons JAR 3ème partie et ressemble à:

public void doSomeWork() {
    try { 
        api.callAndWaitAnswer() ; 
    } 
    catch (InterruptedException e) { throw new AssertionError(); }
}

Maintenant, vous devez gérer un AssertionError (ou tout ce que la bibliothèque que vous utilisez peut jeter). J'ai vu des développeurs expérimentés jettent toutes sortes de bêtises sur les interruptions de recevoir! D'autre part, peut-être la méthode ressemblait à ceci:

public void doSomeWork() {
    while (true) {
        try { 
            return api.callAndWaitAnswer() ; 
        } 
        catch (InterruptedException e) { /* retry! */ }
    }
}

Cette « mauvaise manipulation » d'interruption provoque votre programme en boucle indéfiniment. Encore une fois, ne négligez pas aussi ridicule; il y a beaucoup de mécanismes brisés de traitement d'interruption là-bas.

Au moins en utilisant votre propre drapeau sera complètement invisible pour toutes les bibliothèques 3ème partie.

Il dépend de la mise en œuvre de doSomeWork(). Est-ce que le calcul pur ou le fait (à tout moment) impliquent l'API de blocage (tels que IO) des appels? Par bmargulies de réponse, de nombreuses API de blocage dans JDK sont interruptible et se propagent à l'exception interrompue la pile.

Alors, si le travail implique le blocage des activités potentiellement, vous need'll de prendre en considération les interruptions même si vous décidez de contrôler le processus en utilisant un drapeau, et devrait correctement capturer et manipuler / propager la interruptions.

Au-delà, se reposant sur un drapeau, assurez-vous que votre drapeau est déclarée avec la sémantique volatile.

Je pense que c'est une question de préférence dans la plupart des cas. Personnellement, je pencherais pour le drapeau en main. Il vous donne plus de contrôle - par exemple, de cette façon vous assurez-vous que votre fil ne laisse pas un autre objet dans un état incohérent. Par ailleurs, si la performance est vraiment critique, garder à l'esprit que l'utilisation des exceptions a une surcharge (même si elle est négligeable dans 99% des cas).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top