Demonio viene de la palábra griega daemon. Un daemon es un ser invisible que convive con nosotros que lleva su vida independientemente de la nuestra pero como que convivimos lo que hacen nos puede afectar. Hay demonios de todas clases, bueno, malos, traviesos y serio. La traducción más cercana de la idea de demónio es la de los duendes que son seres que conviven con nosotros pero que hacen su vida y de vez en cuando se divierten fastidiandonos un poco y otras ayudandonos. Un demonio no tiene NADA que ver con el Demonio Cristiano. Un hilo demonio es exactamente eso. Un hilo que se ejecuta en segundo plano, del que no nos enteramos, que hace sus cosas y que de vez en cuando interactua con la ejecución del programa. Como que lo creamos nosotros mismos, a no ser que queramos que sea malo, normalmente es una ayuda a la ejecución normal del programa. El programa acabará cuando acabe el hilo principal. Los demonios mueren con el sin que tengan capacidad para terminar ellos mismos el programa. Se puede averiguar si un hilo es un demonio preguntandole isDaemon(). Y se puede activar o desactivar con setDaemon()
//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();
}
}
Yield() es la orden que indica a la máquina virtual de java que debe devolver el control de la ejecución. Mira este ejemplo de Ping Pong. Tenemos la clase ping y la clase pong y la que las ejecuta. En esta primera versión:
//PingPong.java
class CD_PingThread extends Thread {
public void run() {
while(true) {
System.out.print("ping ");
}
}
}
class CD_PongThread extends Thread {
public void run() {
while(true) {
System.out.print("PONG ");
}
}
}
public class PingPong{
public static void main(String[] args){
CD_PingThread PingThread=new CD_PingThread();
PingThread.start();
CD_PongThread PongThread=new CD_PongThread();
PongThread.start();
}
}
LA ÚNICA MANERA DE SALIR ES CON CONTROL -C Fijate que la máquina virtual de java no sabe cuando debe ceder el control del flujo y lo hace cuando le da la gana por lo que no obtenemos ningun ping- pong. Si por el contrario le introducimos un sleep(tiempo_en_milisegundos) para que se tenga que esperar y ceda el control verás que tampoco conseguimos lo que queremos porque la decisión la toma la máquina virtual y lo hace cuando ella quiere. Si ponemos el mismo tiempo casi siempre lo hace bien, pero a veces falla:
//PingPong.java
class CD_PingThread extends Thread {
public void run() {
while(true) {
System.out.print("ping ");
try {
sleep(10);
}
catch(InterruptedException e) {
return;
}
}
}
}
class CD_PongThread extends Thread {
public void run() {
while(true) {
System.out.println("PONG ");
try {
sleep(10);
}
catch(InterruptedException e) {
return;
}
}
}
}
public class PingPong{
public static void main(String[] args){
CD_PingThread PingThread=new CD_PingThread();
PingThread.start();
CD_PongThread PongThread=new CD_PongThread();
PongThread.start();
}
}
Obtenemos algo tal que así:
ping PONG ping PONG ping PONG ping ping PONG ping PONG ping PONG ping PONG
Para esto es para lo que sirve Yield(). Una vez hecho lo que tiene que hacer el demonio devuelve el control cuando nosotros decidimos que debe devolver el control y esperar a que le vuelva a tocar el turno.
//PingPong.java
import java.io.*;
class CD_PingThread extends Thread {
public void run() {
while(true) {
System.out.print("ping ");
yield();
}
}
}
class CD_PongThread extends Thread {
public void run() {
while(true) {
System.out.println("PONG ");
yield();
}
}
}
public class PingPong{
public static void main(String[] args) throws IOException {
System.out.println("presione enter para iniciar el proceso");
System.out.println("El proceso termina con CONTROL + C");
System.in.read();
CD_PingThread PingThread=new CD_PingThread();
PingThread.start();
CD_PongThread PongThread=new CD_PongThread();
}
}