Como a JVM encerra os threads do daemon? ou como escrever threads daemon que terminam graciosamente

Cenário Hipotético:
Eu tenho um thread daemon responsável por algumas E / S, o segmento principal termina e retorna, e a JVM decide encerrar meu thread daemon.

Como isso acontece? Interromper? Finalizar? Como posso codificar meu thread do daemon para que ele reaja normalmente quando finalizado?

Acabei de escrever o seguinte código como teste:

public class DaemonThreadPlay { public static void main(String [] args) { Thread daemonThread = new Thread() { public void run() { while (true) { try { System.out.println("Try block executed"); Thread.sleep(1000l); } catch (Throwable t) { t.printStackTrace(); } } } @Override public void finalize() { System.out.println("Finalize method called"); } }; daemonThread.setDaemon(true); daemonThread.start(); try { Thread.sleep(2500l); } catch (Throwable t) { //NO-OP } } } 

Eu coloquei breakpoints no bloco catch do thread daemon e no método finalize. Nenhum ponto de interrupção foi atingido, mesmo que o bloco try tenha sido executado. Obviamente, esse código tem problemas de synchronization / tempo, mas acho que podemos concluir com segurança que os threads do daemon não são interrompidos no desligamento nem são seus methods finalize () necessariamente invocados.

Você sempre pode adicionar um gancho de desligamento ao Tempo de Execução da JVM:

 Thread shutdownHook = ... // construct thread that somehow // knows about all the daemon threads Runtime.getRuntime().addShutdownHook(shutdownHook); 

Seu gancho de desligamento pode, obviamente, fazer as tarefas necessárias para um desligamento “normal”.

Eu acho que você entendeu mal o que é um thread daemon.

Veja o que é um thread daemon em java

Em resumo, isso basicamente significa que um encadeamento do daemon não deveria estar fazendo nenhuma E / S ou mantendo nenhum recurso. Se você está violando esta regra básica, então o seu thread não se qualifica como um thread do daemon.

Incluir um gancho de desligamento é a maneira padrão de garantir que seu código seja chamado antes da terminação da JVM, mas mesmo isso não é 100% garantido – sua JVM pode travar, por exemplo, deixando o SO limpar os resources de forma a proteger o sistema operacional , mas muito provavelmente deixa sua aplicação em um estado inconsistente / errôneo.

Os mecanismos de verificação e recuperação do sistema remontam aos primórdios do software (sistemas operacionais e operações em lote, por exemplo) e, infelizmente, essa roda continua sendo reinventada, já que não existe uma abordagem “bala de prata” (API) que resolva esse problema maneira genérica o suficiente.

AFAIK, threads Daemon não são realmente para o trabalho de E / S do stream principal. Se todos os encadeamentos forem concluídos, a JVM poderá fechar todos os encadeamentos do daemon abruptamente. O possível trabalho em torno de sua exigência será criar um ExecutorService como abaixo:

 ExecutorService execPool = Executors.newSingleThreadExecutor(new ThreadFactory() { @Override public Thread newThread(Runnable runnable) { Thread thread = Executors.defaultThreadFactory().newThread(runnable); thread.setDaemon(true); return thread; } }); 

Invoque o método de desligamento do executorervice do gancho Desligamento.

 Runtime.getRuntime().addShutdownHook(....) 

use interrupt e junte-se:

 class Daemon extends Thread { public void run() { while (true) { try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println(e); break; } } System.out.println("exit run()"); } } public class So8663107 { public static void main(String[] arguments) throws InterruptedException { System.out.println(Thread.activeCount()); Daemon daemon = new Daemon(); daemon.setDaemon(true); daemon.start(); Thread.sleep(2500); System.out.println(Thread.activeCount()); daemon.interrupt(); daemon.join(); System.out.println(Thread.activeCount()); } } 
    Intereting Posts