In questa seconda parte della serie Thread in Python, vedremo come sia possibile influenzare l’andamento dell’esecuzione di più thread grazie all’uso dei Join.
Join()
Modifichiamo l’esempio precedente per avere più controllo su ogni singolo thread. Creiamo due thread che attenderanno due tempi diversi, per esempio 10 e 4 secondi. In questo modo saprò sempre che il primo thread durerà a più lungo rispetto al secondo.
Inoltre entrambe I thread dureranno più a lungo dell’esecuzione del programma. I due secondi aggiunti alla fine del programma mi servono per accertarmi che il programma finisca dopo la creazione del secondo thread.
from threading import Thread import time def thread1(): print("Thread 1 started") time.sleep(10) print("Thread 1 ended") def thread2(): print("Thread 2 started") time.sleep(4) print("Thread 2 ended") print("Main start") t1 = Thread(target=thread1) t2 = Thread(target=thread2) t1.start() t2.start() time.sleep(2) print("Main end")
Eseguiamo il codice:
Si vede benissimo che il programma fa partire i due thread e poi dopo due secondi termina. Invece i due thread continueranno a lavorare. Prima si concluderà il secondo thread e poi il primo. Tutto si comporta come volevamo. Eseguendo più volte, avremo sempre lo stesso risultato.
Ma se volessimo una sequenza diversa? Per esempio vogliamo che il programma attendi il termine del secondo thread prima di interrompersi.
Nel modulo threading esiste la funzione Thread.join(). Questa lanciata nel thread obbligherà il programma ad attendere il completamento dell’esecuzione del thread prima di potersi chiudere.
Aggiungiamo quindi al codice di prima il join al secondo thread.
... t2.start() t2.join() time.sleep(2) ...
Ed eseguiamo.
Si vede chiaramente che il programma ora attenderà il termine del secondo thread prima di finire.
Se invece utilizziamo il join() per il primo thread.
t2.start() t1.join() time.sleep(2)
Ed eseguendo..
Vediamo che il programma ora attenderà il termine del primo thread, che essendo quello che impiega più tempo, avremo tutti i thread terminati prima della chiusura del programma.
Ora, eccettuato questo particolare caso, in cui sappiamo benissimo la durata di ciascun thread (abbiamo forzato le cose…), è quasi impossibile prevedere i tempi e le durate di ciascun thread. Se vogliamo che il programma attendi il compimento di tutti i thread è buona norma aggiungere join a tutti i singoli thread.
t1.join() t2.join()
Conclusioni
In questa seconda parte abbiamo visto il ruolo dei Join all’interno dei thread e come questi possano influenzare l’andamento dell’esecuzione di più thread insieme. Nella prossima parte si approfondirà ancora di più l’argomento dei thread, introducendo il Multithreading vero e proprio.