- Ações são implementadas dentro do método
run
da interface funcionalRunnable
(retornavoid
) ou do métodocall
da interface funcionalCallable
(retorno genérico)
- Uma instância da classe
Thread
recebe como parâmetros uma instância que implemente a interfaceRunnable
; o processo é agendado para execução quando o métodostart()
do novo objetoThread
é invocado

- Como um processador pode ter muitas coisas rodando, o que o Java faz é alocar porções de tempo de CPU para executar as threads; com isso uma mesma thread pode trocar de core do CPU de acordo com novas tarefas que vão surgindo
- uma thread pode ser interrompida a qualquer momento para dar lugar a outra thread
- a ordem na qual ações são executadas é incerta; pode ocorrer um cenário onde um mesmo método, que esteja já agendado para execução, finalize depois de um método agendado posteriormente

- Se o método
main
ourun
retornarem, a thread é encerrada
Implementações de Threads
public class Lateral implements Runnable { public void run() {...} } Thread t = new Thread(new Lateral()); t.start();
Runnable
// a classe Thread implementa Runnable public class Lateral extends Thread { public void run() {...} } Thread t = new Lateral(); t.start();
Thread
sobrescrevendo o método run
Runnable r = () -> {...}; Thread t = new Thread(r); t.start();
Runnable
utilizando a sintaxe de Lambda ExpressionThread Life Cycle
Uma Thread não começa a ser executada instantaneamente, o scheduler precisa primeiro alocar tempo de CPU para essa Thread
- Uma thread pode estar nos estados:
NEW
ainda não foi iniciadaRUNNABLE
está sendo executadaBLOCKED
está bloqueada e aguardando uma trava de monitorador ser liberadaWAITING
está aguardando um sinal de outra threadTIMED_WAITING
está esperando um tempo especÃfico de tempoTERMINATED
foi interrompida

- É possÃvel ver o estado "atual" da Thread com o método
getState()
; deve ser levado em consideração que o estado muda muito frequentemente, então o estado retornado pode não ser realmente o atual
- Um Thread já iniciada, não pode ser iniciada novamente; uma mesma instância de
Runnable
pode ser executava múltiplas vezes simultaneamente, porém, cada uma deve ter a sua própriaThread
- Transições para o estado
RUNNABLE
não são instantâneas, pois o scheduler deve alocar tempo de CPU para essa Thread
Interrupção de Thread
- O método
run
deRunnable
é responsável por tomar decisões de mudança de estado; isso quer dizer que o seu código emrun
deve ouvir por mudanças de estado e tomar ações correspondentes - isso quer dizer que seu método
run
decide o que irá acontecer quando o métodointerrupt()
for invocado
- Quando a thread está no estado
RUNNABLE
ela não precisa checar se recebeu um sinal de interrupção; porém, se estiver emWAITING
ouTIMED_WAITING
deve ter um catch para capturar um sinal de interrupção (InterruptedException
)

Bloqueamento de Thread
- É possÃvel definir métodos ou blocos de código sÃncronos, utilizando a palavra reservada
synchronized
- Quando um trecho de código sÃncrono é acessado por uma Thread, ela bloqueia o acesso do escopo imediatamente superior ao trecho de código; esse escopo é chamado de objeto monitor
- se um método estático for sÃncrono — como o método estático pertence a classe, não a uma instância — toda a classe a que esse método pertence, atuará como objeto monitor

- se um método membro de uma classe for sÃncrono, todo acesso à instância que ele pertence será bloqueado até a Thread encerrar a execução desse método
- se um trecho de código, dentro de um método, for sÃncrono, todo acesso a essa instância será bloqueado até a Thread encerrar a execução desse método
- após uma Thread completar sua execução do trecho de código sÃncrono, ela libera o acesso para as outras Threads
Forçar uma Thread a esperar até ser notificada
- O método
wait
da classeObject
coloca uma Thread em estado deWAITING
, até que o métodonotify
ounotifyAll
, desse mesmo objeto monitor — podendo ser uma instância ou uma classe, dependendo do tipo de código sÃncrono que foi executado — for invocado
- O método
notify
de um objeto monitor escolhe, de forma aleatória, uma Thread que esteja aguardando esse objeto monitor para o estadoRUNNABLE
- O método
notifyAll
de um objeto monitor coloca todas Threads que estejam esperando esse objeto monitor no estadoRUNNABLE

Propriedades de uma Thread
- É possÃvel definir um nome para uma Thread no seu construtor
- Uma Thread tem um id único;
getId()
retorna ele
- Uma Thread pode ser definida como um
daemon
ouuser
(padrão éuser
); só é possÃvel definir o tipo da Thread antes dela ser iniciada - a JVM é finalizada quando as únicas Threads remanescentes são do tipo
daemon
(um processo de background)
- Uma Thread pode esperar pela finalização de outra Thread (
join
) - ao invocar
t.join()
a thread que invocou esse método (podendo ser a thread padrão damain
) interrompe sua execução até que a Threadt
seja finalizada
- Uma Thread pode ter uma prioridade; essa prioridade determina quanto de tempo do CPU será alocado para a Thread, mas não garante ordem de execução
- dependendo do sistema onde a aplicação está sendo executada, pode ocorrer da prioridade ser ignorada
Executor
Facilitam o controle de múltiplas threads
Existem diferentes objetos de configuração de
ExecutorService
's:- Fixed Thread Pool: reutiliza um número fixo de threads
- Work Stealing Pool: mantém threads suficientes para manter um certo nÃvel de paralelismo
- Single Thread Executor: utiliza apenas uma thread
- Cached Thread Pool: cria novas threads quando for necessário e reutiliza as existentes
- Scheduled Thread Pool: agenda a execução de
Runnable
's periodicamente ou com um delay
- Single Thread Scheduled Executor: agenda a execução de
Runnable
's com um delay em uma única Thread
- Unconfigurable Executor Service: possibilita o congelamento das configurações de qualquer configuração anterior

Objeto Called
- Ao ser chamado com o método
submit(t)
de algumExecutorService
retorna um objetoFuture<T>
- o objeto
Future
tem um métodoget(<qtd unidades de tempo>, <tipo da unidade de tempo>)
, ao chamar esse método o código aguarda um retorno de resultado até recebê-lo ou lançar um time out de acordo com o tempo definido nos parâmetros
Problemas de Lock
Alguns problemas surgem quando se tenta controlar a natureza aleatória das threads. Esse problemas dependem muito do hardware que executa a aplicação. Como eles dependem do ambiente, se torna absurdamente difÃcil encontra-los. É possÃvel, ainda, que a aplicação não denuncie nenhum erro, mas que a aplicação apenas fique mais lenta ou ela simplesmente pare sua execução.
Para solucionar esse problema existe apenas uma solução: eliminar a dependência entre threads.
Starvation
Ocorre quando uma Thread está aguardando um recurso bloqueado por outra Thread que está ocupada.

Livelock
Ocorre quando uma thread T espera pela finalização de outra thread U, e a thread U espera pela finalização da thread T. Isso gera um loop onde nenhuma thread é finalizada.


Uma Java Thread um caminho de execução e não implica paralelismo fÃsico no CPU