La méthode interrupt() permet d'interrompre un thread en cours d'exécution d'une méthode sleep(), join() ou wait().
Thread thread = new Thread(...); thread.interrupt();
Les méthodes sleep(), join() et wait() produisent une exception InterruptedException, lorsqu'une interruption a été demandée. Si le thread n'exécute pas une des méthodes précitées, la méthode interrupt() modifie l'état d'un indicateur qui pourra être consulté pour gérer éventuellement l'événement survenu.
L'interruption n'affecte que le déroulement d'une méthode susceptible de produire une exception InterruptedException. Le thread en lui même continue à exécuter les instructions de la méthode concernée.
public class Interruption extends Thread { public Interruption() { super(); } public void run() { for (int i = 0; i < 5; i++) { try { for (int j = 0; < 10; j++) { System.out.println(i + " " + j); Thread.sleep(1000); } } catch (InterruptedException e) { System.out.println("Interruption du thread utilisateur !"); } } } public static void main(String[] args) { Interruption thread = new Interruption(); thread.start(); while(thread.isAlive()) { try { Thread.sleep((long)(Math.random() * 10000)); thread.interrupt(); } catch (InterruptedException e) { } } } } /* Affiche : 0 0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 Interruption du thread utilisateur ! 1 0 1 1 1 2 1 3 1 4 1 5 Interruption du thread utilisateur ! 2 0 2 1 Interruption du thread utilisateur ! 3 0 3 1 3 2 Interruption du thread utilisateur ! 4 0 4 1 Interruption du thread utilisateur ! */
Il est possible de détecter l'appel de la méthode d'interruption, ou plus exactement le positionnement d'un indicateur, au sein de l'objet Thread, enjoignant au thread courant de s'interrompre. La méthode isInterrupted() peut être utilisée pour découvrir ce changement d'état de l'indicateur. Dans le cas ou le thread n'exécute pas une méthode sleep(), join() et wait(), cette méthode peut s'avérer très utile.
public class Interruption extends Thread { public Interruption() { super(); } public void run() { long i = 0; while (true) { long premier = -1; if (verifierPremier(i)) premier = i; i++; if (premier > 0 && this.isInterrupted()) { System.out.println("Le thread a été interrrompu !"); System.out.println("Nombre premier : " + premier); premier = -1; break; } } } public boolean verifierPremier(long nombre) { if (nombre < 0) { return false; } else if (nombre < 4) { return true; } else { for (int i = 2; i <= nombre / 2; i++) { if (nombre != i && nombre % i == 0) { return false; } } } return true; } public static void main(String[] args) { Interruption thread = new Interruption(); thread.start(); while (thread.isAlive()) { try { Thread.sleep((long) (Math.random() * 500)); thread.interrupt(); } catch (InterruptedException e) { } } } } /* Affiche : Le thread a été interrrompu ! Nombre premier : 3761 */
Une aute méthode interrupted() retourne le même indicateur d'appel de la méthode interrupt(). La différence par rapport à la méthode isInterrupted() réside que celle-ci est une méthode de classe et donc s'applique sur le nom de la classe Thread.
if(Thread.interrupted()) System.out.println("Le thread a été interrrompu !"); //Equivalent à if(Thread.currentThread().interrupted()) System.out.println("Le thread a été interrrompu !");
Lorsqu'une unité d'exécution est interrompue par l'invocation de la méthode interrupt(), une exception InterruptedException est lancée par certaines méthodes, en l'occurrence sleep(), join() et wait(). L'interruption peut donc être gérée à partir d'un bloc catch().
public class EstimationPI extends Object implements Runnable { public static void main(String[] args) { EstimationPI estimPI = new EstimationPI(0.000000001); Thread thread = new Thread(estimPI); thread.start(); try { Thread.sleep(10000); thread.interrupt(); } catch (InterruptedException e) { } } private double estimationPI; private double precision; public EstimationPI(double precision) { this.precision = precision; this.estimationPI = 0.0; } public void run() { try { System.out.println("CALCUL APPROCHE DE PI " + "AVEC UNE PRECISION DE " + precision); System.out.println(Math.PI + " -> Math.PI"); calculerPI(this.precision); afficherEstimation(); } catch (InterruptedException e) { System.out.println("FIN DE LA PAUSE SUR " + "LE THREAD PRINCIPAL !"); afficherEstimation(); } } private void calculerPI(double precision) throws InterruptedException { long iteration = 0; int signe = -1; while (Math.abs(estimationPI - Math.PI) > this.precision) { if (Thread.interrupted()) { throw new InterruptedException(); } iteration++; signe = -signe; this.estimationPI += signe * 4.0 / ((2 * iteration) - 1); } } private void afficherEstimation() { System.out.println(estimationPI + " -> ESTIMATION DE PI"); } }