HILOS DEMONIO

Anuncio
HILOS DEMONIO
Los hilos de ejecución demonio también se llaman servicios, porque se ejecutan, normalmente,
con prioridad baja y proporcionan un servicio básico a un programa o programas cuando la
actividad de la máquina es reducida.
Los hilos demonio son útiles cuando un hilo debe ejecutarse en segundo plano durante largos
períodos de tiempo.Un ejemplo de hilo demonio que está ejecutándose continuamente es el
recolector de basura (garbage collector). Este hilo, proporcionado por la Máquina Virtual Java,
comprueba las variables de los programas a las que no se accede nunca y libera estos recursos,
devolviéndolos al sistema.
Un hilo puede fijar su indicador de demonio pasando un valor true al método setDaemon(). Si
se pasa false a este método, el hilo de ejecución será devuelto por el sistema como un hilo de
usuario. No obstante, esto último debe realizarse antes de que se arranque el hilo de ejecución
(start()). Si se quiere saber si un hilo es un hilo demonio, se utilizará el método isDaemon().
//Demonios.java
import java.io.*;
class Demonio extends Thread{
private static final int TAMANIO = 10;
private Thread[] t = new Thread[TAMANIO];
public Demonio(){
setDaemon(true);
start();
}
public void run(){
for(int i = 0; i<TAMANIO; i++){
t[i]= new EnjendrarDemonio(i);
}
for(int i=0; i<TAMANIO; i++){
System.out.println("t[" + i + "].isDaemon() = " + t[i].isDaemon() );
}
while(true) yield();
}
}
class EnjendrarDemonio extends Thread{
public EnjendrarDemonio(int i){
System.out.println("Enjendrando demonio " + i );
start();
}
public void run(){
while (true) yield();
}
}
public class Demonios{
public static void main(String[] args) throws IOException{
Thread d = new Demonio();
System.out.println("d.isDaemon() = " + d.isDaemon() );
System.out.println("presione cualquier tecla para terminar");
System.in.read();
}
}
Cambio de Contexto
Si existe una interrupción pendiente es necesario:
Salvar el contexto (PC, registros del procesador, información de la pila) del programa en
ejecución.
Poner en el PC la dirección del programa de tratamiento de la interrupción, que suele
constar de unas pocas tareas básicas.
Una pregunta que puede plantearse es: ¿qué es lo que constituye el contexto que se debe
salvar? La respuesta es que se debe incluir información que pueda ser necesaria para reanudar
el programa interrumpido. Así pues, debe guardarse la parte del bloque de control del proceso
denominada información de estado del procesador. Esto incluye al contador de programa, otros
registros del procesador y la información de la pila.
¿Se tiene que hacer algo más? Ello dependerá de lo que ocurra a continuación. La rutina de
tratamiento de la interrupción es normalmente un programa corto que lleva a cabo unas pocas
tareas básicas relacionadas con una interrupción. Por ejemplo, se marca el indicador que señala
la presencia de una interrupción, puede enviar un acuse de recibo a la entidad que produjo la
interrupción (como un módulo de E/S) y puede hacer algunas tareas básicas relacionadas con
los efectos del suceso que causó la interrupción. Por ejemplo, si la interrupción está relacionada
con un suceso de E/S, el gestor de interrupciones comprobará condiciones de error. Si se ha
producido un error, la rutina de tratamiento puede enviar una señal al proceso que solicitó
originalmente la operación de E/S.
¿Hay que hacer algo más? Pues depende de si la interrupción va a venir seguida de un cambio
de proceso o no. La ocurrencia de una interrupción no siempre causa el cambio de proceso. Es
posible que después de que el gestor de interrupciones se haya ejecutado, el proceso que estaba
ejecutándose reanude su ejecución. En tal caso, tan sólo hay que guardar la información de
estado del procesador y restaurarla para que pueda reanudarse correctamente el proceso
interrumpido (estas funciones son realizadas en hardware).
Por tanto, el cambio de contexto es un concepto distinto al cambio de un proceso. Puede ocurrir
un cambio de contexto sin cambiar el estado del proceso que está actualmente en estado de
ejecución. En tal caso, salvar el contexto y restaurarlo posteriormente involucra un pequeño
coste extra. Sin embargo, si el proceso que estaba ejecutándose tiene que pasar a otro estado
(listo o bloqueado), el sistema operativo tiene que llevar a cabo cambios substanciales en su
entorno( contexto ). Los pasos involucrados en un cambio completo de proceso son los
siguientes:
1.Salvar el contexto del procesador, incluyendo el contador de programa y otros registros.
2.Actualizar el PCB que estaba en estado de ejecución. Esto implica cambiar el estado del
proceso a alguno de los otros estados (listo, bloqueado, suspendido_listo). También se tienen
que actualizar otros campos, como uno en el que se guarde la razón por la que se abandona el
estado de ejecución y otros con información de contabilidad.
3.Mover el PCB a la cola apropiada (listos, bloqueados por el suceso i, suspendido_listo).
4.Seleccionar otro proceso para ejecución (como veremos en el tema de Planificación de
Procesos).
5.Actualizar el PCB seleccionado. Cambiar, por ejemplo, su estado a ‘en ejecución’.
6.Actualizar las estructuras de datos de gestión de la memoria. Esto puede hacer falta
dependiendo de cómo se gestione la traducción de direcciones (lo dejaremos para los temas
sobre memoria).Restaurar el contexto del procesador a aquél que existía en el momento en el
que el proceso seleccionado dejó por última vez el estado de en ejecución, cargando los valores
previos del contador de programa y de otros registros.
Así pues, el cambio de proceso, que implica un cambio de contexto, requiere un esfuerzo
considerablemente superior al de un cambio de contexto.
Que mata al hilo de forma brusca
Un hilo de ejecución se puede morir de dos formas: por causas naturales o porque lo
maten (con stop()).
También se puede matar en cualquier momento un hilo, invocando a su método stop(). En
el trozo de código siguiente:
Thread MiThread = new MiClaseThread();
MiThread.start();
try {
MiThread.sleep( 10000 );
} catch( InterruptedException e ) {
;
}
MiThread.stop();
se crea y arranca el hilo MiThread, se duerme durante 10 segundos y en el momento de
despertarse, la llamada a su método stop(), lo mata.
El método stop() envía un objeto ThreadDeath al hilo de ejecución que quiere detener.
Así, cuando un hilo es parado de este modo, muere asíncronamente. El hilo morirá en el
momento en que reciba ese objeto ThreadDeath.
Los applets utilizarán el método stop() para matar a todos sus hilos cuando el navegador
con soporte Java en el que se están ejecutando le indica al applet que se detengan, por
ejemplo, cuando se minimiza la ventana del navegador o cuando se cambia de página.
El método isAlive()
El interfaz de programación de la clase Thread incluye el método isAlive(), que devuelve
true si el hilo ha sido arrancado (con start()) y no ha sido detenido (con stop()). Por ello,
si el método isAlive() devuelve false, sabemos que estamos ante un Nuevo Thread o ante
un thread Muerto. Si devuelve true, se sabe que el hilo se encuentra en estado Ejecutable
o Parado. No se puede diferenciar entre Nuevo Thread y Muerto, ni entre un hilo
Ejecutable o Parado.
Prioridades de hilo
El intérprete de Java utiliza prioridades para determinar cómo debe comportarse cada hilo con
respecto a los demás. Las prioridades de hilo son valores entre 1 y 10 que indican la prioridad
relativa de un hilo con respecto a los demás.
Método que devuelve verdadero si un hilo es hilo demonio
Si se quiere saber si un hilo es un hilo demonio, se utilizará el método isDaemon().
Métodos para la sincronización
Si se utiliza una clase que no fue diseñada para accesos multihilo y, por ello, dispone de
métodos no sincronizados que manipulan el estado interno, puede envolver la llamada al
método en un bloque sincronizado. El formato general de la sentencia sincronizada es el
siguiente:
synchronized(objeto) sentencia;
En el ejemplo, objeto es cualquier referencia al objeto, y sentencia suele ser un bloque que
incluye una llamada al método de objeto, que solo tendrá lugar una vez que el hilo haya
entrado con éxito en el monitor de objeto.
Java proporciona un mecanismo elegante de comunicación entre procesos, a través de los
métodos wait, notify y notifyAll. Estos métodos se implementan como métodos de final en
Object, de manera que todas las clases disponen de ellos. Cualquiera de los tres métodos sólo
puede ser llamado desde dentro de un método synchronized.



wait: le indica al hilo en curso que abandone el monitor y se vaya a dormir hasta que
otro hilo entre en el mismo monitor y llame a notify.
notify: despierta al primer hilo que realizó una llamada a wait sobre el mismo objeto.
notifyAll_: despierta todos los hilos que realizaron una llamada a wait sobre el mismo
objeto. El hilo con mayor prioridad de los despertados es el primero en ejecutarse.
Documentos relacionados
Descargar