# Programmation évenementielle
https://home.mis.u-picardie.fr/~utard/dokuwiki/doku.php
login : isri
mdp : isri1920
Solution chat python with socket
https://home.mis.u-picardie.fr/~utard/dokuwiki/doku.php?id=m1
## Cours thread
Support cours : https://home.mis.u-picardie.fr/~utard/dokuwiki/doku.php?id=thread
Définition : plusieurs fils d'éxécution éxécuté en même temps
Création d'une boucle pour faire tourner un thread
```
import time
def compterebour(n):
while n>0:
print('T moins',n)
n -=1
time.sleep(5)
```
Création de threads lancant un compte à rebour en utilisant la
```
from threading import Thread
t1=Thread(target=compterebour,args=(5,))
#args=(5,)) = nuplet avec max 5 argument
t2=Thread(target=compterebour,args=(15,))
#lancement des threads
t1.start()
t2.start()
#Attendre la fin du thread précedent
t1.join()
t2.join()
```
VOIR /home/isri/documents/Prog Event/Td2/ ...py
## Cours 3 - vendredi 18 octobre - Multi Threading
Rappel cours :
Les Threads partagent la mémoire et sont constitué de plusieurs processus
### Classe Event :
```
from threading import Thread, Event
>>> import time
>>> e=Event()
>>> def bar():
... while True:
... e.wait()
... print("GET CHEVALED")
... e.clear()
...
>>>
>>> s=Thread(target=bar)
>>> s.start()
>>> e.set()
>>> GET CHEVALED
```
#### Fonction utilisé (voir exemple):
`e.wait`
qui attend l'événement
`e.set `
qui émet l'événement.
`clear`
qui remet l'événement à zéro.
### Classe lock
Exemple simple d'utilisation des locks
```
import threading
import time
lock=threading.Lock()
def foo():
while True:
print("Je prend le lock")
lock.acquire()
print ("J'ai pris le lock")
time.sleep(15)
lock.release()
print ("J'ai relaché le lock")
time.sleep(15)
t=threading.Thread(target=foo)
t.start()
```
*Exercice : Afficher un message lorsqu'on utilise la fonction "release()" :*
from threading import Thread,Lock
import time
l=Lock()
def toto(message):
while True:
l.acquire()
print("message")
time.sleep(5)
l.release()
time.sleep(5)
t=Thread(target=toto,args=("Get Chevaled",))
t.start()
//Pour l'arrêter : l.acquire
#### Fonction utilisé
`acquire()`
qui permet à un seul thread de continuer, les autres sont bloqués
`release()`
qui rend le lock, et permet à un autre thread d'acquérir le lock()
### Classe Condition
Combinaison de la classe event et de la classe Lock
#### Fonction utilisé
acquire()
release()
wait()
notify() / notifyAll()
acquire-> prendre le lock
wait -> il manque un élément, je redonne la main et je m'arrête /!\ Attente
notify-> dit au threads d'attendre
```
from threading import Thread,Condition
c=Condition()
s=0
def un():
global s
c.acquire()
while (s!=1):
c.wait()
print("Un")
s=2
c.notifyAll()
c.release()
def deux():
global s
c.acquire()
while (s!=2):
c.wait()
print("Deux")
s=3
c.notifyAll()
c.release()
def trois():
global s
c.acquire()
while (s!=3):
c.wait()
print("Trois")
s=4
c.notifyAll()
c.release()
t1=Thread(target=un)
t2=Thread(target=deux)
t3=Thread(target=trois)
t1.start()
t2.start()
t3.start()
c.acquire()
s=1
c.notifyAll()
c.release()
```
Au démarrage, les 3 threads vérifie s, passent en "wait" et attendant un signal
S=1 + NotifyAll -> vérification de la condition s=? par les threads
Def "un" s'applique et S=2 etc, etc.. fin
## Exercices
### Producteurs/Consommateurs
Code condition :
from threading import *
import time
c=Condition()
class File:
def __init__(self,n):
self.taille=n
self.i=0
self.file=[]
def put(self,value):
if self.i==self.taille:
raise ValueError("File pleine !")
self.file.append(value)
self.i=self.i+1
def get(self):
if self.i==0:
raise ValueError("File vide !")
self.i=self.i-1
return self.file.pop(0)
def producteur(laFile):
while True:
c.acquire()
while (laFile.i == laFile.taille):
c.wait()
laFile.put(1)
print(laFile.i)
time.sleep(2)
c.notify_all()
c.release()
def consommateur(laFile):
while True:
c.acquire()
while(laFile.i == 0):
c.wait()
laFile.get()
print(laFile.i)
time.sleep(2)
c.notify_all()
c.release()
f=File(3)
t1=Thread(target=producteur,args=(f, ))
t2=Thread(target=consommateur,args=(f, ))
t1.start()
t2.start()
### Barbier
from threading import *
import time
import random
c=Condition()
b=0
s=0
a=[]
def Barbier():
global b,c,s,a
while True:
#if (s==0):
c.acquire()
while(s==0):
b=0
print("[Barbier ] Je fais la sieste")
c.wait()
s=s-1
i=a.pop(0)
print("[Barbier ] Je coiffe le client "+str(i))
time.sleep(2)
print("[Barbier ] J'ai fini le client "+str(i))
c.notify_all()
c.release()
def client(i):
global b,c,s,a
while True:
c.acquire()
#if (s>4):
while(s>4):
print("[Client "+str(i)+"] Le salon est plein, je reviendrai plus tard")
c.wait()
while True:
c.acquire()
print("[Client "+str(i)+"] Je rentre dans le salon")
s=s+1
if(b==0):
print("[Client "+str(i)+"] Je reveille le barbier")
b=1
a.append(i)
print("[Client "+str(i)+"] Je suis en train d'etre coiffe par le barbier")
time.sleep(5)
c.notify_all()
c.release()
print("[Client "+str(i)+"] J'ai fini d'etre coiffe")
print("[Client "+str(i)+"] Je sors du salon")
a.pop(0)
time.sleep(int(random.expovariate(0.1)))
barb=Thread(target=Barbier)
clt=[]
for i in range(5):
clt.append(Thread(target=client, args=(i,)))
barb.start()
for i in range(5):
clt[i].start()
## Serveur de multithreadé
Telnet : outil de connexion à distance sur un port dédié
https://home.mis.u-picardie.fr/~utard/dokuwiki/doku.php?id=serverthread&s[]=mini&s[]=projet