web-dev-qa-db-fra.com

Pourquoi appeler Thread.currentThread.interrupt () dans un bloc catch InterruptException?

Pourquoi invoquer la méthode Thread.currentThread.interrupt() dans le bloc catch?

135
Hesey

Ceci est fait pour garder l'état .

Lorsque vous attrapez InterruptException et que vous l'avalez, vous empêchez essentiellement les méthodes/groupes de threads de niveau supérieur de remarquer l'interruption. Ce qui peut causer des problèmes.

En appelant Thread.currentThread().interrupt(), vous définissez le drapeau d'interruption du thread, afin que les gestionnaires d'interruptions de niveau supérieur le remarquent et puissent le gérer correctement.

La concurrence de Java en pratique en discute plus en détail dans Chapitre 7.1.3: Répondre à une interruption . Sa règle est:

Seul le code qui implémente la politique d'interruption d'un thread peut avaler une demande d'interruption. Le code de la tâche et de la bibliothèque à usage général ne doit jamais avaler les demandes d'interruption.

144
Péter Török

Je pense que cet exemple de code rend les choses un peu claires. La classe qui fait le travail:

   public class InterruptedSleepingThread extends Thread {

        @Override
        public void run() {
            doAPseudoHeavyWeightJob();
        }

        private void doAPseudoHeavyWeightJob() {
            for (int i=0;i<Integer.MAX_VALUE;i++) {
                //You are kidding me
                System.out.println(i + " " + i*2);
                //Let me sleep <evil grin>
                if(Thread.currentThread().isInterrupted()) {
                    System.out.println("Thread interrupted\n Exiting...");
                    break;
                }else {
                    sleepBabySleep();
                }
            }
        }

        /**
         *
         */
        protected void sleepBabySleep() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                //e.printStackTrace();
                Thread.currentThread().interrupt();
            }
        }
    }

La classe principale:

   public class InterruptedSleepingThreadMain {

        /**
         * @param args
         * @throws InterruptedException
         */
        public static void main(String[] args) throws InterruptedException {
            InterruptedSleepingThread thread = new InterruptedSleepingThread();
            thread.start();
            //Giving 10 seconds to finish the job.
            Thread.sleep(10000);
            //Let me interrupt
            thread.interrupt();
        }

    }

Essayez d'appeler une interruption sans rétablir l'état.

63
Ajay George

Remarque:

http://download.Oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

Comment puis-je arrêter un thread qui attend de longues périodes (par exemple, une entrée)?

Pour que cette technique fonctionne, il est essentiel que toute méthode qui attrape une exception d'interruption et qui n'est pas prête à la gérer réitère immédiatement l'exception. Nous disons réaffirme plutôt que renvoyer, car il n'est pas toujours possible de renvoyer l'exception. Si la méthode qui intercepte l'InterruptedException n'est pas déclarée pour renvoyer cette exception (cochée), elle devrait alors "se réinterrompre" avec l'incantation suivante:

Thread.currentThread().interrupt();

Ceci garantit que le thread va relancer l'InterruptedException dès qu'il en sera capable.

20
Bert F

Je considérerais cela comme une mauvaise pratique ou au moins un peu risqué. Habituellement, les méthodes de niveau supérieur n'effectuent pas d'opération de blocage et elles n'y verront jamais InterruptedException. Si vous le masquez à chaque endroit où vous effectuez une opération interruptible, vous ne l'obtiendrez jamais.

La seule raison d'être de Thread.currentThread.interrupt() et de ne pas déclencher une autre exception ou une demande d'interruption de signalisation d'une autre manière (par exemple, en définissant interrupted une variable locale dans la boucle principale d'un thread) est le cas où vous pouvez réellement ne faites rien avec l'exception, comme dans les blocs finally.

Voir la réponse de Péter Török si vous souhaitez mieux comprendre les implications de l'appel Thread.currentThread.interrupt().

2
Piotr Findeisen