128 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			128 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								21 novembre 2008
							 | 
						||
| 
								 | 
							
								Séance 2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Les threads
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								====== Cours ======
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Le but de ce cours est d'utiliser la puissance des nouveaux processeurs pour faire des applications rapides.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								threads = sous partie d'un processus, donc se lance plus vite qu'un processus et prend moins d'espace mémoire
							 | 
						||
| 
								 | 
							
								Faire un thread implique une nouvelle pile d'exécution et de nouveaux registres alloués.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								===== Les Threads, dans Java =====
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Dans la classe Java.lang.Thread, il faut l'interface *Runnable :*, et la méthode *run()* (qui ne prend pas d'arguments).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Faire un thread en Java : 
							 | 
						||
| 
								 | 
							
								  * soit on étend (sous - classer) un thread (à l'aide d'extends)
							 | 
						||
| 
								 | 
							
								  * soit on implémente *Runnable* à notre classe Java.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								===== Comment choisir quelle méthode utiliser ? =====
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Comme Java n'accepte pas l'héritage multiple, mieux vaut implémenter qu'étendre si on a déjà étendu notre classe Java avec une autre.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Implémenter "marche à tout les coups", contrairement à l'autre méthode.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								===== Gestion des priorités =====
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Si un thread n'est pas actif, il ne consommera pas de temps CPU, vu qu'il est mis de côté.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								MAX_PRIORITY et MIN_PRIORITY sont des variables définies dans la classe Thread.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								===== Concurrence d'accès =====
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Pour éviter l'interblocage, on utilise le mot clé *synchronized* pour gérer les concurrences d'accès.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								==== Concurrence d'accès sur une méthode ====
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Le <u>verrou est sur l'instance de la classe</u> et pas sur la classe elle même
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Mettre un verrou pour une instance d'un champ statique (static) n'est pas la bonne solution !!!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								==== Contrôler l'accès à un objet ====
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Utile si la classe a été créée sans être prévue/pensée pour les Threads.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Ceci permet d'utiliser une classe dans des Threads.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								===== Groupes de Threads =====
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Seulement si on a beaucoup de threads (en faisant des *ThreadGroup*).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Permet de lancer un ensemble de threads sans avoir à les instancier l'un après l'autre.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								====== Exercice ======
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								===== Démonstration du cas de l'executor =====
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								3 producteurs ont une liste de produits. Ils gèrent une file d'attente.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Les consommateurs 1 et 2 tentent d'accéder à la file d'attente.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Il faut gérer les processus inactifs et la synchronisation.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* * *
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<code java>
							 | 
						||
| 
								 | 
							
								Executor ex = | Executors.new SingleThread();
							 | 
						||
| 
								 | 
							
								                        | Executors.new ThreadPool(2);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								for (int i=0 ; i < 1 000 ; i++)
							 | 
						||
| 
								 | 
							
								    ex.execute(new Runnable() {
							 | 
						||
| 
								 | 
							
								        public void run() {
							 | 
						||
| 
								 | 
							
								            System.out.println("o")
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								</code>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Dans les exécuteurs il n'y a pas de gestion de dépendances, donc on ne sait pas si le 5ième envoyé sera exécuté après le 4ième : ça faut le faire à la main.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								===== Cas d'interblocage =====
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Tout objet
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<code java>
							 | 
						||
| 
								 | 
							
								class DeadLock {
							 | 
						||
| 
								 | 
							
								    private final Object lock1 = new Object();
							 | 
						||
| 
								 | 
							
								    private final Object lock2 = new Object();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    void a() throws Interrupted Exception {
							 | 
						||
| 
								 | 
							
								        lock1.wait();
							 | 
						||
| 
								 | 
							
								        lock2.notify();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    void b() throws Interrupted Exception {
							 | 
						||
| 
								 | 
							
								        lock2.wait();
							 | 
						||
| 
								 | 
							
								        lock1.notify();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								</code>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Un thread appelle la méthode a() : 
							 | 
						||
| 
								 | 
							
								  * Le lock1 passe en attente.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Un second thread appelle la méthode b() :
							 | 
						||
| 
								 | 
							
								  * Il se met en attente d'un notify (comme le lock1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Donc cela fait un verrou mortel, car on en sort pas. Pourquoi : 
							 | 
						||
| 
								 | 
							
								  * lock1 attend lock1.notify (qui est dans lock2)
							 | 
						||
| 
								 | 
							
								  * lock2 attend lock2.notify (qui est dans lock1, lui même en attente d'un notify)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Nous sommes donc dans un DeadLock.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								===== Explications =====
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wait() : suspend un thread courant
							 | 
						||
| 
								 | 
							
								notify(): réactive UN thread qui a fait un *wait()* sur l'instance
							 | 
						||
| 
								 | 
							
								notifyAll(): réactiver TOUS les threads qui ont fait un *wait()* sur l'instance
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Quand un producteur aura fini de produire, il va activer UN thread pour le consommateur : pour pas mettre sur la paille le second consommateur.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 |