Escritos
Threads
Neste artigo
Threads são as menores unidades de execução dentro de um processo. Elas permitem que várias tarefas sejam executadas de forma concorrente dentro do mesmo programa. Em uma aplicação com várias threads, cada uma tem seu próprio fluxo de execução.
Quando trabalhamos com uma API que escreve em um banco de dados, threads permitem executar operações de forma concorrente. Isso pode melhorar o desempenho e o tempo de resposta da aplicação, já que várias threads podem consultar ou escrever dados ao mesmo tempo.
Sem essa concorrência, as operações teriam que ser executadas uma depois da outra. Com threads, elas podem se sobrepor, reduzindo o tempo necessário para concluir as tarefas.
Mas o acesso concorrente ao banco também pode trazer problemas de inconsistência e condições de corrida. Mecanismos de sincronização, como locks e semáforos, ajudam a controlar o acesso aos recursos compartilhados.
Introdução
Considere um computador com um único núcleo e quatro programas rodando ao mesmo tempo. O computador precisa utilizar concorrência para lidar com esses programas, mesmo que o núcleo só consiga executar uma instrução por vez.
O sistema operacional gerencia o acesso das threads à CPU. Os algoritmos de escalonamento determinam qual delas vai executar em seguida.
- Nesse caso, a impressão de paralelismo vem da alternância entre as tarefas no mesmo núcleo.
Agora considere um computador com dois núcleos e quatro programas rodando ao mesmo tempo. O programa 1 e o programa 2 estão usando o núcleo 1, enquanto o programa 3 e o programa 4 usam o núcleo 2.
Suponha que o programa 1 tenha prioridade alta. Dependendo das decisões do escalonador, ele pode receber mais tempo de CPU, enquanto os outros programas dividem os recursos disponíveis.
Sincronização de threads
Locks, semáforos e sincronização podem ser utilizados para gerenciar recursos compartilhados e resolver problemas de concorrência.
Clique aqui para ver exemplos e entender como eles podem ser utilizados.
Estados de uma thread
Uma thread começa seu ciclo de vida no estado New e permanece nele até ser iniciada.
Quando está pronta para executar, ela entra no estado Runnable. Os estados seguintes dependem do que acontece durante a execução: esperar um recurso, aguardar outra thread ou finalizar o trabalho, por exemplo.
Se não houver nenhum problema, a thread termina depois de concluir sua tarefa. É possível acompanhar esses estados usando logs. O Java tem suporte para isso por meio do java.util.logging.
Uma thread pode estar nos seguintes estados:
-
NewA thread foi criada, mas ainda não foi iniciada.
-
RunnableA thread está pronta para executar ou já está executando.
-
BlockedA thread está esperando para adquirir um monitor, como ao entrar em um bloco
synchronizedocupado por outra thread. -
WaitingA thread está esperando uma ação de outra thread, sem um tempo limite definido.
-
Timed waitingA thread está esperando por um período determinado.
Aqui tem um exemplo usando o método
sleeppara colocar uma thread nesse estado. -
TerminatedA thread terminou porque concluiu sua execução ou por causa de uma exceção não tratada.
Prioridade
Quando uma thread é criada, é possível definir sua prioridade. Se nenhuma prioridade for informada, a thread herda a prioridade da thread que a criou.
No Java, existe uma escala de prioridade de 1 a 10 e as constantes MIN_PRIORITY (1), NORM_PRIORITY (5) e MAX_PRIORITY (10).
O método setPriority(int) pode ser usado para definir a prioridade de uma thread de plataforma.
O sistema operacional também considera outros fatores para gerenciar e escalonar as threads. Então, mesmo que uma prioridade tenha sido definida, ela não garante que aquela thread vai executar primeiro.
Escalonamento
O sistema operacional tem seus próprios algoritmos de escalonamento. Windows, Linux, macOS e outros sistemas podem tomar decisões diferentes sobre quais threads vão executar e por quanto tempo.
Esse é um assunto de sistemas operacionais. Uma referência para estudar o tema está neste link.