Threads
Introdução¶
Exemplo básico
Pseudocódigo
Java
Python
C
escreva("Hello world!");System.out.println("Hello world!");import threading
def tarefa():
print("Executando tarefa...")
t = threading.Thread(target=tarefa)
t.start()
t.join()
print("Finalizado")printf("Hello world!\n");Exemplo com contadores independentes
Pseudocódigo
Java
Python
C
escreva("Hello world!");System.out.println("Hello world!");import threading
from time import sleep
def tarefa_thread():
print("[Thread] Executando tarefa..", flush=True)
for i in range(10):
print(f"[Thread] {i}", flush=True)
sleep(1)
print("[Thread] Finalizado", flush=True)
def tarefa_local():
print("[Main] Executando tarefa..", flush=True)
for i in range(4):
print(f"[Main] {i}", flush=True)
sleep(2)
print("[Main] Finalizado", flush=True)
t = threading.Thread(target=tarefa_thread)
t.start()
tarefa_local()
print("[Main] Aguardando thread finalizar..", flush=True)
t.join()
print("[Main] Finalizado", flush=True)printf("Hello world!\n");Threads com semáforos¶
Pseudocódigo
Java
Python
C
escreva("Hello world!");System.out.println("Hello world!");import threading
import time
WAITING_TIME = 0.1
# Semáforo
semaforo = threading.Semaphore(0)
def thread_0():
for i in range(1, 11):
semaforo.acquire()
print(f"[Thread 0] {i}", flush=True)
semaforo.release()
time.sleep(WAITING_TIME)
def thread_1():
for i in range(1, 11):
semaforo.acquire()
print(f"[Thread 1] {i}", flush=True)
semaforo.release()
time.sleep(WAITING_TIME)
# Instancia as threads
t0 = threading.Thread(target=thread_0)
t1 = threading.Thread(target=thread_1)
# Starta as threads
t0.start()
t1.start()
# Libera o semáforo
semaforo.release()
# Aguarda as threads finalizarem
print("[Main] Aguardando threads")
t0.join()
t1.join()
print("[Main] Finalizado")printf("Hello world!\n");Sockets utilizando Threads¶
Pseudocódigo
Java
Python
C
escreva("Hello world!");System.out.println("Hello world!");Servidor:
import socket
import threading
from time import sleep
HOST = "0.0.0.0"
PORT = 9002
WAITING_TIME = 3
def atender_cliente(conn, addr):
print(f"[Server] Nova conexão {addr}", flush=True)
with conn:
data = conn.recv(1024)
mensagem = data.decode("utf-8")
print(f"[Server] Recebido de {addr}: {mensagem}", flush=True )
print(f"[Server] Processando mensagem..", flush=True )
resposta = mensagem.upper()
sleep(WAITING_TIME)
conn.sendall(resposta.encode("utf-8"))
print(f"[Server] Respondido para {addr}: {resposta}", flush=True)
print(f"[Server] Conexão encerrada {addr}", flush=True)
def iniciar_servidor():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((HOST, PORT))
server.listen()
print(f"Servidor ouvindo em {HOST}:{PORT}")
while True:
conn, addr = server.accept()
thread = threading.Thread(
target=atender_cliente,
args=(conn, addr),
daemon=True
)
thread.start()
if __name__ == "__main__":
iniciar_servidor()Cliente:
import socket
HOST = "127.0.0.1"
PORT = 9002
mensagem = input("[Cliente] Mensagem: ")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as cliente:
cliente.connect((HOST, PORT))
cliente.sendall(mensagem.encode("utf-8"))
resposta = cliente.recv(1024).decode("utf-8")
print(f"[Server] {resposta}")printf("Hello world!\n");Fila protegida¶
Pseudocódigo
Java
Python
C
escreva("Hello world!");System.out.println("Hello world!");Servidor:
import threading
from time import sleep
# Fila de mensagens
FILA = []
# Semáforo de acesso à fila
SEMAFORO_ACESSO = threading.Semaphore(1) # Apenas 1 thread pode acessar a fila por vez
# Quantidade de itens. Quem insere na fila, incrementa. Quem consome, decrementa.
SEMAFORO_ITENS = threading.Semaphore(0) # A fila inicia com 0 elementos
def produzir(mensagem):
global FILA
global SEMAFORO_ACESSO
global SEMAFORO_ITENS
# Aguarda acesso ao recurso
SEMAFORO_ACESSO.acquire()
# Inclui a mensagem na fila
FILA.append(mensagem)
# Libera o acesso ao recurso
SEMAFORO_ACESSO.release()
# Informa que há itens na fila.
SEMAFORO_ITENS.release()
def consumir():
global FILA
global SEMAFORO_ACESSO
global SEMAFORO_ITENS
# Aguarda até que existam itens na fila
SEMAFORO_ITENS.acquire()
# Aguarda acesso ao recurso
SEMAFORO_ACESSO.acquire()
# Verifica se há mensagens na fila
if FILA:
# Retira a primeira mensagem da fila
mensagem = FILA.pop(0)
# Libera o acesso ao recurso
SEMAFORO_ACESSO.release()
# Retorna a mensagem que estava na fila
return mensagem
def thread_produtora(id_thread):
# Inclui mensagens na fila
id_msg = 0
while True:
msg_produzida = f"Mensagem {id_msg}"
print(f"[Thread {id_thread} produziu] {msg_produzida}", flush=True)
produzir(msg_produzida)
id_msg += 1
sleep(1)
def thread_consumidora(id_thread):
# Retira mensagens da fila
while True:
msg_consumida = consumir()
print(f"[Thread {id_thread} consumiu] {msg_consumida}", flush=True)
sleep(1)
def main():
# Cria a thread produtora
t0 = threading.Thread(
target=thread_produtora, args=(0,), # Será a thread 0
daemon=True
)
# Cria 2 threads consumidoras
t1 = threading.Thread(
target=thread_consumidora, args=(1,), # Será a thread 1
daemon=True
)
t2 = threading.Thread(
target=thread_consumidora, args=(2,), # Será a thread 2
daemon=True
)
t0.start()
t1.start()
t2.start()
t0.join()
t1.join()
t2.join()
if __name__ == "__main__":
main()
printf("Hello world!\n");