Java possui um thread especial, o thread daemon, que tem prioridade muito baixa e só será executado quando outros threads do mesmo programa não estiverem em execução.
Como os threads daemon possuem essas características, eles geralmente são usados para fornecer serviços para threads comuns (também chamados de threads de usuário) no programa. Eles geralmente possuem um loop infinito, ou são usados para aguardar solicitações de serviços, ou para executar tarefas, etc. Eles não podem realizar nenhum trabalho importante porque não temos certeza de quando o tempo de CPU será alocado e eles serão encerrados automaticamente quando nenhum outro thread estiver em execução. Uma aplicação típica desse tipo de thread é a coleta de lixo Java.
No exemplo desta seção, criaremos dois threads, um é um thread normal, que grava eventos na fila; o outro é um thread daemon, que limpa eventos na fila e exclui eventos que existem por mais de 10 segundos.
saiba disso
Siga as etapas abaixo para implementar o programa de exemplo.
1. Crie uma classe Event, que é usada apenas para salvar as informações do evento necessárias para a execução do programa. Declare duas propriedades, uma é a propriedade date do tipo java.util.Date e a outra é a propriedade event do tipo String e, em seguida, gere os métodos de leitura e gravação para essas duas propriedades; O código é o seguinte:
Copie o código do código da seguinte forma:
Evento de classe pública {
data privada;
evento String privado;
data pública getData() {
data de retorno;
}
public void setDate(Datadata) {
esta.data = data;
}
string pública getEvent() {
evento de retorno;
}
public void setEvent(String evento) {
este.evento = evento;
}
}
2. Crie uma classe chamada WriterTask e implemente a interface Runnable. O código é o seguinte:
Copie o código do código da seguinte forma:
classe pública WriterTask implementa Runnable {
3. Declare um atributo de fila usado para armazenar eventos, implemente o construtor da classe e use seus parâmetros para inicializar o atributo de fila. O código é o seguinte:
Copie o código do código da seguinte forma:
private Deque<Evento> deque;
public WriterTask(Deque<Evento> deque) {
isto.deque = deque;
}
4. Implemente o método run() desta tarefa, que contém um loop que percorre 100 vezes. Em cada travessia, um novo objeto Event é criado, salvo na fila e suspenso por 1 segundo. O código é o seguinte:
Copie o código do código da seguinte forma:
@Substituir
execução void pública() {
for (int i = 0; i < 100; i++) {
Evento evento = new Event();
event.setDate(nova Data());
event.setEvent(String.format("O thread %s gerou um evento",
Thread.currentThread().getId()));
deque.addFirst(evento);
tentar {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
5. Crie uma classe chamada CleanerTask e herde a classe Thread. O código é o seguinte:
Copie o código do código da seguinte forma:
classe pública CleanerTask estende Thread {
6. Declare um atributo de fila usado para armazenar eventos, implemente o construtor da classe e use seus parâmetros para inicializar o atributo de fila. No método de construção, defina o thread como um thread daemon chamando o método setDaemon(). O código é o seguinte:
Copie o código do código da seguinte forma:
private Deque<Evento> deque;
public CleanerTask(Deque<Evento> deque) {
isto.deque = deque;
setDaemon(verdadeiro);
}
7. Implemente o método run(). Há um loop infinito no corpo do método para obter a hora atual e então chamar o método clearn(). O código é o seguinte:
Copie o código do código da seguinte forma:
@Substituir
execução void pública() {
enquanto (verdadeiro) {
Data data = new Data();
limpar(data);
}
}
8. Implemente o método clean(). Neste método, obtenha a última hora e verifique a diferença de horário entre a hora e a hora atual. Se foi criado há 10 segundos, exclua o evento atual e verifique o próximo. evento. Caso um evento seja deletado, as informações sobre o evento deletado serão impressas, e o último comprimento da fila também será impresso, para que o andamento da execução do programa possa ser observado. O código é o seguinte:
Copie o código do código da seguinte forma:
private void clean(Data data) {
longa diferença;
exclusão booleana;
if (deque.size() == 0) {
retornar;
}
excluir = falso;
fazer {
Evento e = deque.getLast();
diferença = date.getTime() - e.getDate().getTime();
se (diferença > 10.000) {
System.out.printf("Limpador: %s/n", e.getDate());
deque.removeLast();
excluir = verdadeiro;
}
} while (diferença > 10000);
se (excluir) {
System.out.printf("Clearner: Tamanho da fila: %d/n", deque.size());
}
}
9. Crie a classe principal do programa, a classe Main, e então implemente o método main(). O código é o seguinte:
Copie o código do código da seguinte forma:
classe pública Principal {
public static void main(String[] args) {
10. Use a classe Deque para criar uma fila para armazenar eventos. O código é o seguinte:
Copie o código do código da seguinte forma:
Deque<Evento> deque = new ArrayDeque<>();
11. Crie e inicie três threads WriterTask e um thread CleanerTask. O código é o seguinte:
Copie o código do código da seguinte forma:
Deque<Evento> deque = new ArrayDeque<>();
Escritor WriterTask = new WriterTask(deque);
for (int i = 0; i < 3; i++) {
Thread thread = new Thread(escritor);
thread.start();
}
CleanerTask limpador = new CleanerTask(deque);
limpador.start();
12. Execute o programa e visualize os resultados da execução.
sabe por que
Analisando os resultados da execução do programa, podemos ver que a fila primeiro aumenta para 30, e depois muda entre 27 e 30 até que a execução do programa termine.
O programa primeiro começa a ser executado a partir de três threads WriterTask. Cada thread primeiro adiciona um evento à fila e depois dorme por 1 segundo. Após os primeiros 10 segundos, haverá trinta eventos na fila. Durante esses 10 segundos, quando todos os três threads WriterTask estiverem suspensos, o thread CleanerTask também será executado, mas nenhum evento será excluído porque o tempo de geração de todos os eventos não excede 10 segundos. Após os primeiros 10 segundos, três WriterTasks adicionam três eventos à fila a cada segundo; da mesma forma, CleanerTask exclui três eventos a cada segundo; Portanto, o número de eventos oscila entre 27 e 30.
Quando todos os threads do WriterTask estão inativos, ficamos livres para processar o tempo, permitindo que o thread daemon seja executado durante esse tempo. Se você definir o tempo de suspensão do thread WriterTask para ser mais curto, o thread CleanerTask terá menos tempo de execução da CPU. Se for esse o caso, o comprimento da fila continuará a aumentar porque o encadeamento CleanerTask nunca obtém tempo de execução suficiente para excluir eventos suficientes.
sem fim
O thread só pode ser definido como um thread daemon chamando o método setDaemon() antes de chamar o método start(). Depois que um thread começa a ser executado, o estado do daemon não pode ser modificado.
Você também pode usar isDaemon() para verificar se um thread é um thread daemon. Se for um thread daemon, retorna verdadeiro; se for um thread comum, retorna falso.
Usar doutrina
Este artigo foi traduzido do "Java 7 Concurrency Cookbook" (D Gua Ge o roubou como "Java7 Concurrency Sample Collection") e é usado apenas como material de aprendizagem. Não pode ser utilizado para quaisquer fins comerciais sem autorização.
Pequeno sucesso
Versões completas de todos os códigos de exemplo usados nesta seção.
Código completo da classe Event
Copie o código do código da seguinte forma:
pacote com.diguage.books.concurrencycookbook.chapter1.recipe7;
importar java.util.Date;
/**
*Aula de informações do evento
* Data: 19/09/2013
* Horário: 22h56
*/
Evento de classe pública {
data privada;
evento String privado;
data pública getData() {
data de retorno;
}
public void setDate(Datadata) {
esta.data = data;
}
string pública getEvent() {
evento de retorno;
}
public void setEvent(String evento) {
este.evento = evento;
}
}
Código completo da classe WriterTask
Copie o código do código da seguinte forma:
pacote com.diguage.books.concurrencycookbook.chapter1.recipe7;
importar java.util.Date;
importar java.util.Deque;
importar java.util.concurrent.TimeUnit;
/**
* Gere um evento a cada segundo.
* Data: 19/09/2013
* Horário: 22h59
*/
classe pública WriterTask implementa Runnable {
private Deque<Evento> deque;
public WriterTask(Deque<Evento> deque) {
isto.deque = deque;
}
@Substituir
execução void pública() {
for (int i = 0; i < 100; i++) {
Evento evento = new Event();
event.setDate(nova Data());
event.setEvent(String.format("O thread %s gerou um evento",
Thread.currentThread().getId()));
deque.addFirst(evento);
tentar {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Código completo da classe CleanerTask
Copie o código do código da seguinte forma:
pacote com.diguage.books.concurrencycookbook.chapter1.recipe7;
importar java.util.Date;
importar java.util.Deque;
/**
* Limpeza de eventos
* Data: 19/09/2013
* Horário: 23h33
*/
classe pública CleanerTask estende Thread {
private Deque<Evento> deque;
public CleanerTask(Deque<Evento> deque) {
isto.deque = deque;
setDaemon(verdadeiro);
}
@Substituir
execução void pública() {
enquanto (verdadeiro) {
Data data = new Data();
limpar(data);
}
}
/**
* Excluir evento.
*
* @param data
*/
private void clean(Data data) {
longa diferença;
exclusão booleana;
if (deque.size() == 0) {
retornar;
}
excluir = falso;
fazer {
Evento e = deque.getLast();
diferença = date.getTime() - e.getDate().getTime();
se (diferença > 10.000) {
System.out.printf("Limpador: %s/n", e.getDate());
deque.removeLast();
excluir = verdadeiro;
}
} while (diferença > 10000);
se (excluir) {
System.out.printf("Clearner: Tamanho da fila: %d/n", deque.size());
}
}
}
O código completo da classe principal
Copie o código do código da seguinte forma:
pacote com.diguage.books.concurrencycookbook.chapter1.recipe7;
importar java.util.ArrayDeque;
importar java.util.Deque;
/**
* Data: 19/09/2013
* Horário: 23h54
*/
classe pública Principal {
public static void main(String[] args) {
Deque<Evento> deque = new ArrayDeque<>();
Escritor WriterTask = new WriterTask(deque);
for (int i = 0; i < 3; i++) {
Thread thread = new Thread(escritor);
thread.start();
}
CleanerTask limpador = new CleanerTask(deque);
limpador.start();
}
}