web-dev-qa-db-fra.com

Comment puis-je tuer un fil? sans utiliser stop ();

Thread currentThread=Thread.currentThread();
        public void run()
        {               

             while(!shutdown)
            {                               
                try
                {
                    System.out.println(currentThread.isAlive());
                Thread.interrupted();

                System.out.println(currentThread.isAlive());
                if(currentThread.isAlive()==false)
                {
                    shutdown=true;
                }
                }
                catch(Exception e)
                {
                    currentThread.interrupt();
                }                   
            }
        }

    });
    thread.start();
24
greeshma

L'alternative à l'appel d'arrêt est d'utiliser l'interruption pour signaler au thread que vous voulez qu'il termine ce qu'il fait. (Cela suppose que le thread que vous souhaitez arrêter se comporte bien, s'il ignore les exceptions d'interruption en les mangeant immédiatement après leur lancement et ne vérifie pas l'état interrompu, vous revenez à l'utilisation de stop ().)

Voici du code que j'ai écrit en réponse à une question de thread ici , c'est un exemple du fonctionnement de l'interruption de thread:

public class HelloWorld {

    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(new Runnable() {

            public void run() {
                try {
                    while (!Thread.currentThread().isInterrupted()) {
                        Thread.sleep(5000);
                        System.out.println("Hello World!");
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        thread.start();
        System.out.println("press enter to quit");
        System.in.read();
        thread.interrupt();
    }
}

Quelques choses à savoir:

  • Une interruption provoque immédiatement la levée de sleep() et wait(), sinon vous êtes coincé en attendant que le temps de sommeil soit écoulé.

  • Notez qu'il n'est pas nécessaire d'avoir un indicateur booléen distinct.

  • Le thread étant arrêté coopère en vérifiant l'état interrompu et en interceptant les InterruptedExceptions en dehors de la boucle while (en l'utilisant pour quitter la boucle). L'interruption est un endroit où il est correct d'utiliser une exception pour le contrôle de flux, c'est tout l'intérêt.

  • La définition d'interruption sur le thread en cours dans le bloc catch est techniquement la meilleure pratique mais est exagérée pour cet exemple, car il n'y a rien d'autre qui a besoin de l'indicateur d'interruption défini.

Quelques observations sur le code affiché:

  • L'exemple publié est incomplet, mais placer une référence au thread actuel dans une variable d'instance semble être une mauvaise idée. Il sera initialisé sur le thread qui crée l'objet, pas sur le thread exécutant la méthode run. Si la même instance de Runnable est exécutée sur plusieurs threads, la variable d'instance ne reflétera pas le bon thread la plupart du temps.

  • La vérification pour savoir si le thread est vivant va nécessairement toujours aboutir à true (sauf s'il y a une erreur où la variable d'instance currentThread fait référence au mauvais thread), Thread#isAlive Est faux seulement après que le thread a fini de s'exécuter, il ne renvoie pas faux simplement parce qu'il a été interrompu.

  • L'appel de Thread#interrupted Entraînera la suppression du drapeau d'interruption et n'a aucun sens ici, d'autant plus que la valeur de retour est ignorée. Le point d'appeler Thread#interrupted Est de tester l'état du drapeau interrompu puis de le supprimer, c'est une méthode pratique utilisée par les choses qui jettent InterruptedException.

57
Nathan Hughes

En règle générale, un thread se termine lorsqu'il est interrompu . Alors, pourquoi ne pas utiliser le booléen natif? Essayez isInterrupted () :

   Thread t = new Thread(new Runnable(){
        @Override
        public void run() {
            while(!Thread.currentThread().isInterrupted()){
                // do stuff         
            }   
        }});
    t.start();

    // Sleep a second, and then interrupt
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {}
    t.interrupt();
14
mre

Une bonne façon de le faire serait d'utiliser un drapeau booléen pour signaler le thread.

class MyRunnable implements Runnable {

    public volatile boolean stopThread = false;

    public void run() {
            while(!stopThread) {
                    // Thread code here
            }
    }

}

Créez une instance MyRunnable appelée myrunnable, enveloppez-la dans une nouvelle instance Thread et démarrez l'instance. Lorsque vous souhaitez marquer le thread pour qu'il s'arrête, définissez myrunnable.stopThread = true. De cette façon, il ne s'arrête pas au milieu de quelque chose, seulement là où nous nous attendons à ce qu'il s'arrête.

6
Raze