Interrompre un thread correctement

[Fermé]
Signaler
Messages postés
19
Date d'inscription
dimanche 29 août 2010
Statut
Membre
Dernière intervention
1 mars 2013
-
Messages postés
16400
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
21 septembre 2021
-
Bonjour,

J'utilise une bibliothèque externe pour changer d'ip et parfois, très rarement, l'appel à la méthode qui permet de changer l'ip bug et boucle indéfiniment. Dans ce cas là, je me retrouve avec un thread qui ne se termine jamais, et au bout d'un moment ces threads qui bouclent sans raison se font nombreux.

Mon but, c'est de terminer de façon la plus propre possible le thread qui boucle si il ne s'est pas terminé de lui même au bout de 5 secondes.

public class MonProgramme
{
	public static void main(String[] args) 
	{	
		Thread t = new MonObjet();
		t.start();
		Thread.sleep(5000);
		// Ici je veux placer une ligne réalisant l'action suivante : 
		// Si thread non fini alors l'interrompre.
	}
}

public class MonObjet extends Thread implements Runnable
{
	public void run()
	{
		System.out.println("Le thread vient de se lancer !");

		Librairie.boucle_infinie();

		System.out.println("Le thread vient de se terminer !");
	}
}


Je ne peux en aucun cas toucher au code de Librairie.boucle_infinie() (appelée comme ça seulement pour l'exemple)

Comment puis-je interrompre mon thread proprement ?

Merci d'avance et bonne journée !

Cordialement,
Reywas

4 réponses

Messages postés
16400
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
21 septembre 2021
2 879
extends Thread implements Runnable
Thread implémente déjà Runnable, ce n'est pas la peine de le rappeler.

public static void main(String[] args) throws InterruptedException
{	
	Thread t = new MonObjet();
	t.start();
	
	Thread.sleep(5000);
	
	// Arrêt spécifique du Thread t
	if (!t.isInterrupted())
		t.interrupt();
	
	// Arrêt de la machine virtuelle (tous les Thread sont arrêtés)
	System.exit(0);
}
Messages postés
19
Date d'inscription
dimanche 29 août 2010
Statut
Membre
Dernière intervention
1 mars 2013
1
Merci mais cela ne fonctionne pas :/

t.interrupt() est bien exécuté mais le thread continue de tourner.

public class MonProgramme  
{  
	public static void main(String[] args)  throws InterruptedException  
	{   
		Thread t = new MonObjet();  
		t.start();  
		Thread.sleep(5000);  

		if (!t.isInterrupted())  
		{ System.out.println("1"); t.interrupt();}  
    
		if (!t.isInterrupted())  
		{ System.out.println("2"); }  
	}  
}  

public class MonObjet extends Thread  
{  
	public void run()  
	{  
		System.out.println("Le thread vient de se lancer !");  

		while(true)  
		{  
			System.out.println("Boucle");  
			try { Thread.sleep(500); }catch(Exception e){}  
		}  

		System.out.println("Le thread vient de se terminer !");  
	}  
}


En effet, je vois s'afficher le message "boucle" pendant 5 secondes, jusque là tout est normal. Au bout des 5 secondes comme le thread n'est pas interrompu je vois le message "1" s'afficher, toujours comme prévu. Ensuite le thread est interrompu et je ne vois pas s'afficher le message "2", mais le thread tourne toujours puisque le message "boucle" continue d'apparaître...

Je veux vraiment que le thread soit détruit, qu'il s'arrête complètement et qu'il ne continue pas de tourner dans le vent.

Comment faire ?
Messages postés
16400
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
21 septembre 2021
2 879
Lorsqu'on utilise la méthode interrupt, une exception InterruptedException est envoyée au Thread, or cette exception tu l'as court-circuité en faisant un try/catch qui ne fait rien.

public void run()
{
	System.out.println("Le thread démarre !");
	
	try
	{
		while(true)
		{
			System.out.println("Boucle");
			Thread.sleep(500);
		}
	}
	catch (InterruptedException e)
	{
		System.out.println(e.getMessage());
	}
	
	System.out.println("Le thread se termine !");
}

Remarque : même si c'est un peu "violent" pour une utilisation courante, je te conseille de mettre systématiquement le System.exit(0) à la fin de ton main, afin d'être sûr que tous les threads du programme seront arrêtés même si tes interruptions échouent.
Messages postés
19
Date d'inscription
dimanche 29 août 2010
Statut
Membre
Dernière intervention
1 mars 2013
1
Grand merci pour ton aide mais ça ne fonctionne toujours pas. En effet sur l'exemple que tu donnes c'est bon mais dés qu'on enlève le sleep dans le while alors ça ne s'interrompt plus.

Or la méthode qui pose problème, celle qui crée la boucle infinie (voir premier post pour se remémorrer) n'a probablement pas de sleep.

Donc le code suivant ne fonctionne pas : (D'ailleurs il compile même pas)

public class MonProgramme  
{  
	public static void main(String[] args)  throws InterruptedException  
	{   
		Thread t = new MonObjet();  
		t.start();  
		Thread.sleep(5000);  
		t.interrupt();

	}  
}  

public class MonObjet extends Thread  
{  
	public void run()  
	{  
		try
		{
		        Librairie.boucle_infinie();
                }
		catch (InterruptedException e)
		{
			System.out.println(e.getMessage());
		}
	}  
}


Comment puis-je régler cela ?
Messages postés
16400
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
21 septembre 2021
2 879
Voici ce qu'indique la documentation officielle : Java Thread Primitive Deprecation

What if a thread doesn't respond to Thread.interrupt?

In some cases, you can use application specific tricks. For example, if a thread is waiting on a known socket, you can close the socket to cause the thread to return immediately. Unfortunately, there really isn't any technique that works in general. It should be noted that in all situations where a waiting thread doesn't respond to Thread.interrupt, it wouldn't respond to Thread.stop either. Such cases include deliberate denial-of-service attacks, and I/O operations for which thread.stop and thread.interrupt do not work properly.

Cela signifie que si le code est bien fait, un thread devrait prendre en charge ce changement d'état, c'est à dire tester lui même s'il est ou non interrompu et s'arrêter en conséquence.

public void run()  
{  
	System.out.println("Le thread démarre !");  
	
	while (true)
	{
		System.out.println("Boucle");
		
		if (isInterrupted())
			break;
		
		/*
		try 
		{
			Thread.sleep(500);
		} 
		catch (InterruptedException e)
		{
			break;
		}
		*/
	}
	
	System.out.println("Le thread s'arrete");
}

Mais comme indiqué dans la documentation, il n'y a pas de méthode générale si cette opération échoue. Il reste cependant la possibilité de faire le System.exit(0) qui lui marchera forcément, mais ne fera pas dans le détail puisqu'il arrêtera tout le programme.