Quero um objeto que gerará um encadeamento daemon que continuará sendo executado durante o tempo de vida do processo. Digamos, apenas por uma questão de argumento, que é um encadeamento em um sistema incorporado e aguarda para receber e manipular comandos em alguma porta de diagnóstico. Mas, poderia ser qualquer coisa realmente. A idéia principal é que ele esteja assistindo algo por um longo período de tempo; Não está executando uma sequência de tarefas .
A sabedoria comum sobre Java diz: Nunca instancia Thread
, use um ExecutorService
. (Por exemplo, veja esta resposta ) Mas qual é o benefício? Usar um conjunto de encadeamentos como um meio para criar um único encadeamento de longa execução parece inútil. Como seria melhor do que se eu escrevesse isso?
class Foobar {
public Foobar() {
this.threadFactory = Executors.defaultThreadFactory();
...
}
public Foobar(ThreadFactory threadFactory) {
this.threadFactory = threadFactory;
...
}
public void start() {
fooThread = threadFactory.newThread(new Runnable() { ... });
fooThread.setDaemon(true);
fooThread.start();
}
...
}
Nota: esta pergunta parece semelhante à minha, mas as respostas dizem apenas como usar um pool de threads, não o porquê .
fonte
Respostas:
Eu acho que "Nunca" é uma palavra muito forte. É mais como a segunda regra de otimização: "Não (ainda)".
Na minha opinião, o principal motivo para usar um serviço executor é gerenciar o número de threads em execução. Se você permitir que classes arbitrárias criem seus próprios encadeamentos, poderá se encontrar rapidamente com 1.000 encadeamentos vinculados à CPU (ou com alternância constante de contexto). Um serviço executor resolve esse problema, fornecendo restrições na criação do encadeamento.
Um motivo secundário é que o início adequado de um encadeamento requer alguma reflexão:
System.exit()
para desligar o programa.Dito isto, certamente há casos em que é apropriado ativar threads em vez de confiar em um pool de threads.
"Gerado externamente" depende do contexto. O caso clássico é o encadeamento no final de uma fila ou soquete de mensagens, que precisa pesquisar essa fila e executar alguma ação (que pode envolver o envio de uma tarefa para um pool).
No entanto, também pode se referir a eventos gerados fora de um módulo específico: por exemplo, considero perfeitamente razoável que o Log4J gire
AsyncAppender
seu próprio encadeamento em vez de esperar que o aplicativo forneça um pool.fonte