Java tiene un subproceso especial, el subproceso daemon, que tiene una prioridad muy baja y sólo se ejecutará cuando otros subprocesos del mismo programa no se estén ejecutando.
Debido a que los subprocesos de demonio tienen estas características, generalmente se utilizan para proporcionar servicios a subprocesos ordinarios (también llamados subprocesos de usuario) en el programa. Generalmente tienen un bucle infinito, o se utilizan para esperar solicitudes de servicios, o para realizar tareas, etc. No pueden realizar ningún trabajo importante porque no estamos seguros de cuándo se les asignará tiempo de CPU y finalizarán automáticamente cuando no se estén ejecutando otros subprocesos. Una aplicación típica de este tipo de subprocesos es la recolección de basura de Java.
En el ejemplo de esta sección, crearemos dos subprocesos, uno es un subproceso normal, que escribe eventos en la cola; el otro es un subproceso demonio, que borra eventos en la cola y elimina eventos que existen durante más de 10 segundos.
lo sabes
Siga los pasos a continuación para implementar el programa de muestra.
1. Cree una clase de evento, que solo se utiliza para guardar la información del evento necesaria para la ejecución del programa. Declare dos propiedades, una es la propiedad de fecha del tipo java.util.Date y la otra es la propiedad de evento del tipo String y luego genere los métodos de lectura y escritura para estas dos propiedades; El código es el siguiente:
Copie el código de código de la siguiente manera:
Evento de clase pública {
fecha privada fecha;
evento de cadena privado;
fecha pública getDate() {
fecha de regreso;
}
setDate público vacío (Fecha fecha) {
this.date = fecha;
}
cadena pública getEvent() {
evento de regreso;
}
setEvent vacío público (evento de cadena) {
this.event = evento;
}
}
2. Cree una clase llamada WriterTask e implemente la interfaz Runnable. El código es el siguiente:
Copie el código de código de la siguiente manera:
La clase pública WriterTask implementa Runnable {
3. Declare un atributo de cola utilizado para almacenar eventos, implemente el constructor de la clase y use sus parámetros para inicializar el atributo de cola. El código es el siguiente:
Copie el código de código de la siguiente manera:
privado Deque<Evento> deque;
public WriterTask(Deque<Evento> deque) {
this.deque = deque;
}
4. Implemente el método run() de esta tarea, que contiene un bucle que lo recorre 100 veces. En cada recorrido, se crea un nuevo objeto Evento, luego se guarda en la cola y duerme durante 1 segundo. El código es el siguiente:
Copie el código de código de la siguiente manera:
@Anular
ejecución pública vacía() {
para (int i = 0; i < 100; i++) {
Evento evento = nuevo Evento();
event.setDate(nueva fecha());
event.setEvent(String.format("El hilo %s ha generado un evento",
Thread.currentThread().getId()));
deque.addFirst(evento);
intentar {
Unidad de tiempo.SEGUNDOS.dormir(1);
} captura (Excepción interrumpida e) {
e.printStackTrace();
}
}
}
5. Cree una clase llamada CleanerTask y herede la clase Thread. El código es el siguiente:
Copie el código de código de la siguiente manera:
La clase pública CleanerTask extiende el hilo {
6. Declare un atributo de cola utilizado para almacenar eventos, implemente el constructor de la clase y use sus parámetros para inicializar el atributo de cola. En el método de construcción, configure el hilo como un hilo de demonio llamando al método setDaemon(). El código es el siguiente:
Copie el código de código de la siguiente manera:
privado Deque<Evento> deque;
public CleanerTask(Deque<Evento> deque) {
this.deque = deque;
setDaemon(verdadero);
}
7. Implemente el método run(). Hay un bucle infinito en el cuerpo del método para obtener la hora actual y luego llamar al método clearn(). El código es el siguiente:
Copie el código de código de la siguiente manera:
@Anular
ejecución pública vacía() {
mientras (verdadero) {
Fecha fecha = nueva Fecha();
limpio(fecha);
}
}
8. Implemente el método clean(). En este método, obtenga la última hora y luego verifique la diferencia horaria entre la hora y la hora actual. Si se creó hace 10 segundos, elimine el evento actual y luego verifique el siguiente. evento. Si se elimina un evento, se imprimirá la información sobre el evento eliminado y también se imprimirá la última longitud de la cola, para que se pueda observar el progreso de ejecución del programa. El código es el siguiente:
Copie el código de código de la siguiente manera:
limpieza nula privada (Fecha fecha) {
larga diferencia;
eliminación booleana;
si (deque.tamaño() == 0) {
devolver;
}
eliminar = falso;
hacer {
Evento e = deque.getLast();
diferencia = fecha.getTime() - e.getDate().getTime();
si (diferencia > 10000) {
System.out.printf("Limpiador: %s/n", e.getDate());
deque.removeLast();
eliminar = verdadero;
}
} mientras (diferencia > 10000);
si (eliminar) {
System.out.printf("Clearner: Tamaño de la cola: %d/n", deque.size());
}
}
9. Cree la clase principal del programa, la clase Main, y luego implemente el método main(). El código es el siguiente:
Copie el código de código de la siguiente manera:
clase pública principal {
público estático vacío principal (String [] argumentos) {
10. Utilice la clase Deque para crear una cola para almacenar eventos. El código es el siguiente:
Copie el código de código de la siguiente manera:
Deque<Evento> deque = new ArrayDeque<>();
11. Cree e inicie tres subprocesos WriterTask y un subproceso CleanerTask. El código es el siguiente:
Copie el código de código de la siguiente manera:
Deque<Evento> deque = new ArrayDeque<>();
WriterTask escritor = new WriterTask(deque);
para (int i = 0; i < 3; i++) {
Hilo hilo = nuevo hilo (escritor);
hilo.start();
}
Limpiador CleanerTask = nuevo CleanerTask(deque);
limpiador.start();
12. Ejecute el programa y vea los resultados de la ejecución.
saber por qué
Al analizar los resultados de la ejecución del programa, podemos ver que la cola primero aumenta a 30 y luego cambia entre 27 y 30 hasta que finaliza la ejecución del programa.
El programa primero comienza a ejecutarse desde tres subprocesos de WriterTask. Cada subproceso primero agrega un evento a la cola y luego duerme durante 1 segundo. Después de que hayan pasado los primeros 10 segundos, habrá treinta eventos en la cola. Durante estos 10 segundos, cuando los tres subprocesos de WriterTask duermen, el subproceso de CleanerTask también se ejecutará, pero no se eliminará ningún evento porque el tiempo de generación de todos los eventos no supera los 10 segundos. Después de los primeros 10 segundos, tres WriterTasks agregan tres eventos a la cola cada segundo; de manera similar, CleanerTask elimina tres eventos cada segundo; Así, el número de eventos oscila entre 27 y 30.
Cuando todos los subprocesos de WriterTask están inactivos, somos libres de procesar el tiempo, permitiendo que el subproceso del demonio se ejecute durante este tiempo. Si configura el tiempo de suspensión del subproceso WriterTask para que sea más corto, el subproceso CleanerTask obtendrá menos tiempo de ejecución de la CPU. Si este es el caso, la longitud de la cola seguirá creciendo porque el subproceso CleanerTask nunca tiene suficiente tiempo de ejecución para eliminar suficientes eventos.
interminable
El hilo solo se puede configurar como un hilo de demonio llamando al método setDaemon() antes de llamar al método start(). Una vez que un hilo comienza a ejecutarse, el estado del demonio no se puede modificar.
También puedes usar isDaemon() para comprobar si un hilo es un hilo de demonio. Si es un hilo de demonio, devuelve verdadero; si es un hilo normal, devuelve falso.
Usar doctrina
Este artículo está traducido del "Libro de cocina de concurrencia de Java 7" (D Gua Ge lo robó como "Colección de ejemplos de concurrencia de Java 7") y solo se utiliza como material de aprendizaje. No puede utilizarse con fines comerciales sin autorización.
Pequeño éxito
Versiones completas de todo el código de muestra utilizado en esta sección.
Código completo de la clase de evento.
Copie el código de código de la siguiente manera:
paquete com.diguage.books.concurrencycookbook.chapter1.recipe7;
importar java.util.Fecha;
/**
*Clase de información del evento
* Fecha: 2013-09-19
* Hora: 22:56
*/
Evento de clase pública {
fecha privada fecha;
evento de cadena privado;
fecha pública getDate() {
fecha de regreso;
}
setDate public void(Fecha fecha) {
this.date = fecha;
}
cadena pública getEvent() {
evento de regreso;
}
setEvent público vacío (evento de cadena) {
this.event = evento;
}
}
Código completo de la clase WriterTask
Copie el código de código de la siguiente manera:
paquete com.diguage.books.concurrencycookbook.chapter1.recipe7;
importar java.util.Fecha;
importar java.util.Deque;
importar java.util.concurrent.TimeUnit;
/**
* Generar un evento cada segundo.
* Fecha: 2013-09-19
* Hora: 22:59
*/
La clase pública WriterTask implementa Runnable {
privado Deque<Evento> deque;
public WriterTask(Deque<Evento> deque) {
this.deque = deque;
}
@Anular
ejecución pública vacía() {
para (int i = 0; i < 100; i++) {
Evento evento = nuevo Evento();
event.setDate(nueva fecha());
event.setEvent(String.format("El hilo %s ha generado un evento",
Thread.currentThread().getId()));
deque.addFirst(evento);
intentar {
Unidad de tiempo.SEGUNDOS.dormir(1);
} captura (Excepción interrumpida e) {
e.printStackTrace();
}
}
}
}
Código completo de la clase CleanerTask
Copie el código de código de la siguiente manera:
paquete com.diguage.books.concurrencycookbook.chapter1.recipe7;
importar java.util.Fecha;
importar java.util.Deque;
/**
* Limpieza de eventos
* Fecha: 2013-09-19
* Hora: 23:33
*/
La clase pública CleanerTask extiende el hilo {
privado Deque<Evento> deque;
public CleanerTask(Deque<Evento> deque) {
this.deque = deque;
setDaemon(verdadero);
}
@Anular
ejecución pública vacía() {
mientras (verdadero) {
Fecha fecha = nueva Fecha();
limpio(fecha);
}
}
/**
* Eliminar evento.
*
* fecha @param
*/
limpieza nula privada (Fecha fecha) {
larga diferencia;
eliminación booleana;
si (deque.tamaño() == 0) {
devolver;
}
eliminar = falso;
hacer {
Evento e = deque.getLast();
diferencia = fecha.getTime() - e.getDate().getTime();
si (diferencia > 10000) {
System.out.printf("Limpiador: %s/n", e.getDate());
deque.removeLast();
eliminar = verdadero;
}
} mientras (diferencia > 10000);
si (eliminar) {
System.out.printf("Clearner: Tamaño de la cola: %d/n", deque.size());
}
}
}
El código completo de la clase principal.
Copie el código de código de la siguiente manera:
paquete com.diguage.books.concurrencycookbook.chapter1.recipe7;
importar java.util.ArrayDeque;
importar java.util.Deque;
/**
* Fecha: 2013-09-19
* Hora: 23:54
*/
clase pública principal {
público estático vacío principal (String [] argumentos) {
Deque<Evento> deque = new ArrayDeque<>();
WriterTask escritor = new WriterTask(deque);
para (int i = 0; i < 3; i++) {
Hilo hilo = nuevo hilo (escritor);
hilo.start();
}
Limpiador CleanerTask = nuevo CleanerTask(deque);
limpiador.start();
}
}