Resumo : neste tutorial, você aprenderá como usar o objeto Event de threading do Python para se comunicar entre threads.
Introdução ao objeto de evento de threading Python
Às vezes, você precisa se comunicar entre os threads . Para fazer isso, você pode usar um lock (mutex) e uma variável booleana.
No entanto, Python fornece uma maneira melhor de comunicação entre threads usando a Event
classe do threading
módulo.
A Event
classe oferece uma maneira simples, mas eficaz de coordenar threads: um thread sinaliza um evento enquanto outros threads esperam por ele.
O Event
objeto envolve um sinalizador booleano que pode ser definido ( True
) ou desmarcado ( False
). Vários threads podem esperar que um Event
seja definido antes de continuar ou podem redefinir Event
o estado desmarcado.
A seguir ilustramos as etapas para usar o Event
objeto:
Primeiro, importe do Event
módulo threading
:
from threading import Event
Linguagem de código: Python ( python )
A seguir, crie um novo Event
objeto:
event = Event()
Linguagem de código: Python ( python )
Por padrão, o evento não está definido (desmarcado). O is_set()
método do objeto de evento retornará False
:
if event.is_set():
# ...
Linguagem de código: Python ( python )
Em seguida, defina um evento usando o set()
método:
event.set()
Linguagem de código: Python ( python )
Assim que um evento for definido, todos os threads que aguardam o evento serão notificados automaticamente.
Depois disso, desmarque um evento através do clear()
método:
event.clear()
Linguagem de código: Python ( python )
Finalmente, os threads podem esperar que o evento seja definido através do wait()
método:
event.wait()
Linguagem de código: Python ( python )
O wait()
método bloqueia a execução de um thread até que o evento seja definido. Em outras palavras, o wait()
método bloqueará o thread atual até que outro thread chame o set()
método para definir o evento.
Se um evento for definido, a wait()
função retornará imediatamente.
Para especificar quanto tempo o thread irá esperar, você pode usar o argumento timeout. Por exemplo:
event.wait(timeout=5) # wait for 5 seconds
Linguagem de código: Python ( python )
Exemplo de evento de threading Python
O exemplo a seguir mostra um exemplo simples de uso do Event
objeto para comunicação entre threads:
from threading import Thread, Event
from time import sleep
def task(event: Event, id: int) -> None:
print(f'Thread {id} started. Waiting for the signal....')
event.wait()
print(f'Received signal. The thread {id} was completed.')
def main() -> None:
event = Event()
t1 = Thread(target=task, args=(event,1))
t2 = Thread(target=task, args=(event,2))
t1.start()
t2.start()
print('Blocking the main thread for 3 seconds...')
sleep(3)
event.set()
if __name__ == '__main__':
main()
Linguagem de código: Python ( python )
Saída:
Thread 1 started. Waiting for the signal....
Thread 2 started. Waiting for the signal....
Blocking the main thread for 3 seconds...
Received signal. The thread 1 was completed.
Received signal. The thread 2 was completed.
Linguagem de código: Python ( python )
Como funciona.
Primeiro, defina a task()
função que aceita um Event
objeto e um número inteiro:
def task(event: Event, id: int) -> None:
print(f'Thread {id} started. Wait for the signal....')
event.wait()
print(f'Receive signal. The thread {id} was completed.')
Linguagem de código: Python ( python )
Dentro da task()
função, chamamos o wait()
método do objeto de evento para aguardar que o evento seja definido pelo thread principal.
Segundo, crie um Event
objeto dentro da main()
função:
event = Event()
Linguagem de código: Python ( python )
Terceiro, crie dois threads filhos que executam a task()
função com o mesmo objeto de evento e IDs 1 e 2 diferentes:
t1 = Thread(target=task, args=(event,1))
t2 = Thread(target=task, args=(event,2))
Linguagem de código: Python ( python )
Quarto, inicie ambos os threads chamando o start()
método:
t1.start()
t2.start()
Linguagem de código: Python ( python )
Quinto, chame o sleep()
método para bloquear o thread principal por três segundos:
sleep(3)
Linguagem de código: Python ( python )
Como a task()
função chama o wait()
método do objeto de evento, ambos t1
os t2
threads aguardarão a definição do evento antes de continuar.
Finalmente, defina o evento chamando o set()
método do thread principal:
event.set()
Linguagem de código: Python ( python )
Ambos t1
os t2
threads serão notificados e continuarão em execução até o final.
Observe que você aprenderá como usar o objeto Event para interromper um thread filho do thread principal no próximo tutorial.
Exemplo prático de utilização do evento Threading
O exemplo a seguir ilustra como usar o evento threading para sincronizar entre dois threads:
- O thread nº 1 baixa um arquivo de texto de URL
https://www.ietf.org/rfc/rfc793.txt
e, uma vez concluído, notifica o segundo thread para contar as palavras do arquivo de texto baixado. - O thread nº 2 é iniciado e aguarda o sinal concluído do thread nº 1. Ao receber o sinal, ele começa a contar as palavras do arquivo baixado.
Aqui está o programa completo:
from threading import Thread, Event
from urllib import request
def download_file(url, event):
# Download the file form URL
print(f"Downloading file from {url}...")
filename, _ = request.urlretrieve(url, "rfc793.txt")
# File download completed, set the event
event.set()
def process_file(event):
print("Waiting for the file to be downloaded...")
event.wait() # Wait for the event to be set
# File has been downloaded, start processing it
print("File download completed. Starting file processing...")
# Count the number of words in the file
word_count = 0
with open("rfc793.txt", "r") as file:
for line in file:
words = line.split()
word_count += len(words)
# Print the word count
print(f"Number of words in the file: {word_count}")
def main():
# Create an Event object
event = Event()
# Create and start the file download thread
download_thread = Thread(target=download_file,
args=("https://www.ietf.org/rfc/rfc793.txt", event))
download_thread.start()
# Create and start the file processing thread
process_thread = Thread(target=process_file, args=(event,))
process_thread.start()
# Wait for both threads to complete
download_thread.join()
process_thread.join()
print("Main thread finished.")
if __name__ == '__main__' :
main()
Linguagem de código: PHP ( php )
Resumo
- Use a
threading.Event
classe para comunicação entre threads. - Use o
set()
método para definir o evento eclear()
o método para cancelar a configuração do evento. - Use o
is_set()
método para verificar se um evento está definido. - Use o
wait()
método para aguardar a definição do evento.