Considere o seguinte código:
public... main( String[] args ) // yeah yeah, I'm too lazy to type it out
new ThreadExample().start(); // the run function just prints out "this is run"
}
Agora, pode acontecer que no momento em que a chamada para iniciar seja feita, o escalonador volte para o bloco principal e o bloco principal termine. O que acontecerá com o thread que o método start criou? Ainda há um thread não-daemon em execução (aquele que criamos), o que significa que o programa deve continuar a execução ou pode se tornar um thread zumbi (ainda não entendo completamente o que isso implica...). O que poderia acontecer (ou o que se passa por “poderia” na ausência de sincronização)?
Editar:
Esta pergunta é melhor reformulada como: "O que exatamente a chamada do método start() faz?"
Mais informações podem ser encontradas em: Por que chamamos o método Thread.start()?
DR
No seu exemplo, o thread será iniciado e a JVM não será encerrada até que o thread também termine (a menos que um evento de desligamento diferente seja acionado). Você não precisa de sincronização extra para isso.
descrição mais longa
Você está iniciando o thread no seu método principal. Como o
start()
método termina antes demain
ser interrompido, o aplicativo não será encerrado. Conforme mencionado nos comentários da sua pergunta (e também diretamente na sua pergunta), a JVM não tenta desligar antes que todos os threads não-daemon sejam interrompidos.Quando você cria um thread, ele estará dentro
ThreadState.NEW
, mas assim que você chamarstart()
, ele estará dentroThreadState.RUNNABLE
(ou similar, se já tiver realizado algum trabalho) e impedirá o encerramento do aplicativo.Se um thread não for
NEW
nemTERMINATED
, ele estará ativo, portanto, impedirá o encerramento da JVM.Portanto, seu segundo thread continuaria em execução até terminar ou qualquer outra coisa interromper a JVM.
Assim que você ligar
Thread#start
, você terá um thread impedindo o encerramento da JVM, independentemente de o thread realmente ter começado a funcionar.No entanto, conforme mencionado nos comentários , isso pode ser diferente se
Thread#start
for invocado após a interrupção do último thread não-daemon. Se a JVM já estiver sendo encerrada, chamarThread#start
outro thread não cancelará o encerramento.Se o último encadeamento não-daemon parar e um encadeamento daemon tentar iniciar um encadeamento não-daemon "ao mesmo tempo", você terá uma condição de corrida e o encadeamento poderá vencer ou ser interrompido.
Se o thread estiver realmente marcado como iniciado antes do último thread (thread não daemon) parar, ele será executado normalmente e a JVM não será encerrada.
No entanto, se a JVM detectar que todos os encadeamentos foram interrompidos antes que o novo encadeamento seja marcado como iniciado/
RUNNABLE
, a JVM iniciaria a sequência de desligamento e encerraria o encadeamento recém-iniciado após a conclusão de todos os ganchos de desligamento.Se você estiver usando threads virtuais, deve-se observar que estes sempre são threads daemon.
Para sua informação: você deve ter ouvido falar de "zumbis" do Linux. Linux, os processos referem-se a outros processos por seus PIDs (IDs de processo) em todo o sistema . O sistema operacional reutiliza PIDs, mas nunca reutilizará o PID C* até que algum processo ativo P* receba uma notificação de que C morreu e que seu PID não é mais válido. Isso acontece quando P chama
wait()
ou uma das várias outras chamadas de sistema semelhantes.Um processo zumbi no Linux é simplesmente o PID de algum processo morto para o qual nenhum outro processo vivo recebeu ainda o aviso de falecimento. Se o próprio processo P morrer sem nunca esperar por seu filho zumbi C, então o
init
processo morreráwait
para ambos, e o zumbi será colhido.A única maneira pela qual os zumbis podem ser um problema é se o processo P for executado por um longo tempo e criar continuamente novos filhos, sem nunca
wait
precisar de nenhum deles. PIDs são um recurso limitado e, eventualmente, a tabela de processos pode ficar tão obstruída com zumbis quefork()
as chamadas começam a falhar comENOMEM
.Não estou ciente de nada semelhante acontecendo com threads Java. O objeto Java
Thread
que representa um thread morto é gerenciado (lixo coletado) como qualquer outro objeto Java, e se o sistema operacional exigir algum tipo de limpeza após o thread nativo subjacente ter terminado, AFAIK, a JVM deve cuidar disso automaticamente para você.* Estou usando “P” para “pai” e “C” para “filho” porque essa é a forma mais comum de um processo saber o PID de outro.