Pular para o conteúdo principal

Guia definitivo: tutorial de threading em Python

Aprenda os conceitos básicos de threading e como usá-los com a ajuda do Python.
Atualizado 17 de set. de 2026  · 12 min lido

Explorar com IA

ChatGPTClaudePerplexity

Se você está começando em Python e quer aprender mais, faça o curso Introduction to Data Science in Python da DataCamp.

graphic

Introdução

Threading permite que partes diferentes do seu processo sejam executadas de forma concorrente (Fonte: RealPython). Essas partes diferentes geralmente são individuais e possuem uma unidade de execução separada pertencente ao mesmo processo. Um processo nada mais é do que um programa em execução que tem unidades individuais capazes de rodar em paralelo. Por exemplo, um navegador pode ser um processo; um aplicativo que executa várias câmeras simultaneamente pode ser um processo; um videogame é outro exemplo de processo.

Dentro de um processo, surge o conceito de múltiplas threads, popularmente conhecido como multi-threading, em que várias threads trabalham juntas para alcançar um objetivo comum. O maior benefício de usar threads é permitir que o programa seja executado em paralelo.

Vamos entender o conceito de threading com um exemplo. Imagine que você tem um aplicativo que conta o número de carros entrando e saindo do estacionamento de um shopping. Seu equipamento tem várias câmeras que monitoram a entrada e a saída, conectadas a um dispositivo central. Cada câmera terá um algoritmo para monitorar o fluxo de carros, todos pertencentes ao mesmo processo ou programa. Porém, cada câmera, junto com o algoritmo que roda sobre ela, pode fazer parte de uma thread separada. Mais ainda: a leitura dos frames da câmera e a inferência do algoritmo nesses frames também poderiam ser duas threads distintas.

Outro exemplo é um videogame em que o processo precisa executar tarefas em paralelo, como gráficos, interação do usuário e rede (em jogos multiplayer), já que ele precisa ser responsivo o tempo todo. Para isso, usa o conceito de multi-threading, no qual cada thread fica responsável por uma tarefa independente.

Uma thread tem seu próprio fluxo de execução, o que significa que o processo terá várias coisas acontecendo ao mesmo tempo.

É importante notar que todo processo tem pelo menos uma thread, chamada de main thread. Se o seu programa não define threads adicionais, ele terá pelo menos a thread principal, ou seja, o próprio processo.

Se você observar o diagrama acima, há um processo que contém a thread principal com variáveis globais e três threads diferentes: t1, t2 e t3. Cada thread tem suas variáveis locais e seu próprio fluxo de execução do código. As threads geralmente compartilham os recursos do processo: os recursos disponíveis para a thread principal também serão compartilhados entre t1, t2 e t3. Todas as threads terão acesso às variáveis globais, mantendo suas variáveis locais.

Existem diferentes tipos de threads:

  • Thread de kernel
  • Thread de usuário
  • Combinação de thread de kernel e de usuário

Agora, veja algumas vantagens de usar threading no seu programa:

  • O multi-threading pode acelerar a execução do programa, desde que haja múltiplas CPUs.

  • Ele também permite executar outras tarefas enquanto operações de I/O estão ocorrendo, usando várias threads ou até a thread principal junto com uma única thread. Por exemplo, a velocidade com que os frames da câmera são lidos e processados pelo algoritmo pode ser gerenciada por threads diferentes. Assim, o algoritmo não precisa esperar a leitura de um frame, e a leitura não precisa aguardar o fim da execução do algoritmo para ler o próximo frame.

  • Threads dentro do mesmo processo podem compartilhar a memória e os recursos da thread principal.

Desafios do threading

  • Lembre-se de que o Python, na implementação CPython, limita a execução a apenas uma thread por vez; portanto, threading pode não acelerar todas as tarefas. O motivo principal é o Global Interpreter Lock (GIL).

    Se quiser aprender mais sobre o GIL, confira este tutorial.

  • Se o seu objetivo é acelerar tarefas intensivas de CPU, threading pode não ser a melhor solução. Nesses casos, o multi-processing costuma ser mais adequado.

  • Para executar um programa com várias threads, é necessário alternar rapidamente entre elas; por isso, o agendamento (scheduling) precisa ser bem planejado em programas com muitas threads.

  • O compartilhamento de recursos também pode ser um problema, já que todas as threads compartilham os mesmos recursos e a memória de variáveis globais. Assim, operações feitas em uma thread podem causar erro de memória em outra, ou outra thread pode não obter memória suficiente para executar sua tarefa.

Threading em Python

  • No Python, o módulo de threading é nativo, chama-se threading e pode ser importado diretamente.

  • Como quase tudo em Python é representado como objeto, threads também são objetos. Uma thread é capaz de:

    • Conter dados,
    • Ser armazenada em estruturas como dicionários, listas, sets etc.
    • Ser passada como parâmetro para uma função.

  • Uma thread também pode ser executada como um processo.

  • Uma thread em Python pode ter vários estados, como:

    • Wait (aguardando),
    • Locked (bloqueada).

Agora vamos aprender como implementar threading em Python.

Módulo thread no Python 3

Observe que o Python 3 mantém compatibilidade com o módulo thread, existente no Python 2.7. No Python 3, ele pode ser importado como módulo _thread. Vamos ver um exemplo para entender o módulo _thread.

import _thread #thread module imported
import time #time module

Vamos definir uma função chamada thread_delay, que recebe dois parâmetros de entrada: o nome da thread e o atraso. Dentro dessa função, você vai:

  • Definir um contador iniciado em zero,
  • Criar um laço while que roda três vezes,
  • Dentro do while, usar time.sleep() para adicionar atraso — útil para entender a execução da thread. O atraso é em segundos,
  • Incrementar o contador em 1,
  • Para verificar se a execução da thread está fluindo, imprimir o nome da thread e o horário em que a thread foi executada.
def thread_delay(thread_name, delay):
    count = 0
    while count < 3:
        time.sleep(delay)
        count += 1
        print(thread_name, '-------->', time.time())

Agora, para adicionar a funcionalidade de thread à função acima — ou executá-la em uma thread — você usaria o método start_new_thread, que fica dentro do módulo _thread.

Vamos ver a docstring do método start_new_thread.

?_thread.start_new_thread
Threading in Python Tutorial

Vamos passar a função thread_delay sem parênteses e os dois argumentos — o nome da thread e o atraso (para visualizar a execução da thread, já que é muito rápida).

_thread.start_new_thread(thread_delay, ('t1', 1))
_thread.start_new_thread(thread_delay, ('t2', 3))
10916



t1 --------> 1588077856.4221454
t1 --------> 1588077857.4418247
t2 --------> 1588077858.422453
t1 --------> 1588077858.4431
t2 --------> 1588077861.4371448
t2 --------> 1588077864.438915

No output acima, você vê que a thread t1 começa a executar primeiro. Enquanto isso, a thread t2 aguarda, pois tem um atraso de 3 segundos; assim que o atraso termina, t2 é executada — lembrando que o atraso de t1 é de apenas 1 segundo.

Agora vamos alterar o atraso de t2 para 5 segundos, o que fará t2 iniciar depois que t1 terminar sua execução, já que t1 leva apenas 3 segundos para concluir.

_thread.start_new_thread(thread_delay, ('t1', 1))
_thread.start_new_thread(thread_delay, ('t2', 5))
14632



t1 --------> 1588078001.4087512
t1 --------> 1588078002.4272866
t1 --------> 1588078003.432218
t2 --------> 1588078005.4082909
t2 --------> 1588078010.4268317
t2 --------> 1588078015.4283602

Implementando threading com o módulo threading

Vamos usar o mesmo exemplo acima, mas agora com o módulo threading em vez de _thread.

import threading
import time
def thread_delay(thread_name, delay):
    count = 0
    while count < 3:
        time.sleep(delay)
        count += 1
        print(thread_name, '-------->', time.time())

No módulo threading há uma classe Thread, em espírito semelhante à função start_new_thread do módulo _thread.

Vamos ver a docstring da classe Thread, que recebe vários parâmetros como group, target (uma função), args etc.

?threading.Thread
Threading in Python Tutorial

No construtor da classe Thread, você passa a função alvo thread_delay e os argumentos dessa função.

t1 = threading.Thread(target=thread_delay, args=('t1', 1))
t2 = threading.Thread(target=thread_delay, args=('t2', 3))

No módulo threading, para executar a thread você usa o método start(), responsável por iniciá-la.

?t1.start
Threading in Python Tutorial
t1.start()
t2.start()
t1 --------> 1588081121.7790291
t1 --------> 1588081122.7962046
t2 --------> 1588081123.7789369
t1 --------> 1588081123.7980876
t2 --------> 1588081126.7961557
t2 --------> 1588081129.7995002

Você também pode usar o método join, que faz a thread atual aguardar até que a execução das outras threads termine. Ou seja, qualquer código após join só será executado quando essas threads forem finalizadas.

?t1.join
Threading in Python Tutorial
t1.start()
t2.start()

t1.join()
t2.join()

print("Thread execution is complete!")
t1 --------> 1588081798.7118263
t1 --------> 1588081799.7231226
t2 --------> 1588081800.7129223
t1 --------> 1588081800.730732
t2 --------> 1588081803.7298765
t2 --------> 1588081806.7309563
Thread execution is complete!

Agora vamos calcular o volume de um cubo e de um quadrado usando threading — é bem direto.

def volume_cube(a):
    print ("Volume of Cube:", a*a*a)
def volume_square(a):
    print ("Volume of Square:", a*a)
t1 = threading.Thread(target=volume_cube, args=(2))
t2 = threading.Thread(target=volume_square, args=(3))
t1.start()
t2.start()

t1.join()
t2.join()

print("Thread execution is complete!")
Thread execution is complete!


Exception in thread Thread-9:
Traceback (most recent call last):
  File "C:\Program Files\Anaconda3\lib\threading.py", line 926, in _bootstrap_inner
    self.run()
  File "C:\Program Files\Anaconda3\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
TypeError: volume_square() argument after * must be an iterable, not int
Exception in thread Thread-8:
Traceback (most recent call last):
  File "C:\Program Files\Anaconda3\lib\threading.py", line 926, in _bootstrap_inner
    self.run()
  File "C:\Program Files\Anaconda3\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
TypeError: volume_cube() argument after * must be an iterable, not int

Ué, como assim? Ao executar o método start, ocorreu um erro. Isso acontece porque o parâmetro args espera uma tupla e, como volume_cube e volume_square esperam apenas um parâmetro, você precisa colocar uma vírgula no args após especificar o primeiro argumento das funções.

t1 = threading.Thread(target=volume_cube, args=(2,))
t2 = threading.Thread(target=volume_square, args=(3,))
t1.start()
t2.start()

t1.join()
t2.join()

print("Thread execution is complete!")
Volume of Cube: 8
Volume of Square: 9
Thread execution is complete!

Agora vamos aprender a usar threading como subclasse.

Threading como subclasse

Nesta seção, você vai aprender a criar uma subclasse a partir da classe Thread, disponível no módulo threading, e então criar as instâncias t1 e t2 dessa classe.

Vamos reutilizar a função thread_delay aqui também.

class DataCampThread(threading.Thread):
    def __init__(self, name, delay):
        threading.Thread.__init__(self)
        self.name = name
        self.delay = delay


    def run(self):
        print('Starting Thread:', self.name)
        thread_delay(self.name,self.delay)
        print('Execution of Thread:', self.name, 'is complete!')


t1 = DataCampThread('t1', 1)
t2 = DataCampThread('t2', 3)    

t1.start()
t2.start()

t1.join()
t2.join()

print("Thread execution is complete!")
Starting Thread: t1
Starting Thread: t2
t1 --------> 1588089083.4879806
t1 --------> 1588089084.489222
t1 --------> 1588089085.4909666
Execution of Thread: t1 is complete!
t2 --------> 1588089085.4979634
t2 --------> 1588089088.499365
t2 --------> 1588089091.5012596
Execution of Thread: t2 is complete!
Thread execution is complete!

Entenda o código acima, passo a passo:

  • Você definiu uma classe DataCampThread e, como argumento de classe, passou threading.Thread. A razão é criar uma subclasse do módulo threading. Assim, você pode usar todos os métodos disponíveis em threading.Thread, de forma semelhante à herança.

  • Em seguida, você definiu o método init da classe DataCampThread e passou o nome e o delay. O init é um construtor; semelhante aos parâmetros que você passaria para threading.Thread, aqui você passa para DataCampThread.

  • Depois, você inicializa o init da classe base threading.Thread e atribui name e delay.

  • Na sequência, define o método run. Lembre que aqui você chamou o método start, que por baixo dos panos chama run. Como você herdou a classe principal, pode alterar o método run. Assim, quando chamar start, as modificações em run serão aplicadas.

Conclusão

Parabéns por concluir o tutorial.

Este foi uma introdução básica ao threading em Python. No entanto, threading é um tema amplo e essencial, e alguns conceitos podem ter ficado de fora. Sinta-se à vontade para explorar outros métodos, como active_count, current_thread, etc.

Se quiser aprender mais, confira também a documentação de Thread-based Parallelism do Python.

Se você está começando em Python e quer aprender mais, faça o curso Introduction to Data Science in Python da DataCamp.

Tópicos
Python

Cursos de Python

Curso

Introdução ao Python

4 h
7M
Domine os fundamentos da análise de dados com Python em quatro horas e explore pacotes populares.
Ver detalhesRight Arrow
Iniciar Curso
Ver maisRight Arrow
Relacionado

Tutorial

Tutorial de lambda em Python

Aprenda uma maneira mais rápida de escrever funções em tempo real com as funções lambda.
DataCamp Team's photo

DataCamp Team

3 min

Tutorial

Desenvolvimento backend com Python: guia completo para iniciantes

Este guia completo ensina os fundamentos do desenvolvimento backend com Python. Aprenda conceitos básicos, frameworks e boas práticas para começar a criar aplicações web.
Oluseye Jeremiah's photo

Oluseye Jeremiah

15 min

Tutorial

Tutorial do Python pandas: O guia definitivo para iniciantes

Você está pronto para começar sua jornada com os pandas? Aqui está um guia passo a passo sobre como você pode começar.
Vidhi Chugh's photo

Vidhi Chugh

15 min

Tutorial

Tutorial sobre loops em Python

Um tutorial introdutório completo sobre loops em Python. Aprenda e pratique loops while e for, loops aninhados, as palavras-chave break e continue, a função range e muito mais!
Satyabrata Pal's photo

Satyabrata Pal

15 min

Tutorial

Programação orientada a objetos em Python (OOP): Tutorial

Aborde os fundamentos da programação orientada a objetos (OOP) em Python: explore classes, objetos, métodos de instância, atributos e muito mais!
Théo Vanderheyden's photo

Théo Vanderheyden

12 min

Tutorial

Tutorial sobre concatenação de strings em Python

Aprenda vários métodos para concatenar strings em Python, com exemplos para ilustrar cada técnica.
DataCamp Team's photo

DataCamp Team

5 min

Ver MaisVer Mais