No es un bug, es una característica no documentada

lunes, 14 de diciembre de 2015

Procesos y servicios. Prioridad de los hilos

En el lenguaje de programación Java, cada hilo tiene una prioridad. Por defecto  un hilo hereda la prioridad del hilo padre que lo crea.


El método setPriority() permite aumentar o disminuir la prioridad. getPriority() retorna la prioridad del hilo.

La prioridad va de 1 a 10
  • MIN_PRIORITY à 1
  • MAX_PRIORITY  à 10
  • NORM_PRIORITY à 5

Si dos o más hilos tienen la misma prioridad, la máquina virtual va cediendo la prioridad de forma cíclica (round-robin).

En Windows los valores del contador dependerán de la prioridad asignada al hilo, y en sistemas Linux (Ubuntu) los valores de los contadores no dependen de la prioridad asignada al hilo.

Cuando un hilo entra en ejecución y no cede voluntariamente el control para que puedan ejecutarse otros hilos, se dice que es un “hilo egoísta”. Windows combate esta situación con una estrategia de planificación por división de prioridad que compiten por la CPU.

A la hora de programar hilos con prioridades hemos de tener en cuenta que el comportamiento no está garantizado y dependerá de la plataforma en la que se ejecutan los programas.

En la práctica casi nunca hay que establecer a mano las prioridades.

Ejercicios de gestión de hilos

Un ejercicio típico para gestión de hilos y su sincronización es el problema del productor consumidor.

Vamos a ver cuatro tipos de este problema. Intentad haced cada uno por vuestra cuenta y comprobad el resultado posteriormente.

1. Modifica la clase Productor para que envíe las cadenas PING y PONG (de forma alternativa, una vez PING y otra vez PONG) a la cola y la clase Consumidor tome la cadena de la cola y la visualice.

La salida tiene que mostrar lo siguiente: PING PONG PING PONG PING PONG PING PONG PING PONG PING PONG PING PONG PING PONG PING PONG PING PONG PING PONG PING PONG PING PONG PING....

ARCHIVO COLA.JAVA

package Actividad26_productorConsumidor1;

public class Cola {
      
       private int numero;
       private boolean disponible = false; //inicialmente cola vacía 
      
       public synchronized int get() {
            
              
             while(disponible == false){ 
                    try{
                           wait();
                    }catch (InterruptedException e){}
             }//fin de while
             System.out.println("PONG");
             disponible=false;
             notifyAll();
             return numero; //se devuelve
      
       }//Fin de get
      
      
       public synchronized void put() {
            
             while (disponible == true){
                    try {
                           wait();
                    }catch (InterruptedException e){}
             }
             System.out.println("PING");
             disponible=true; //disponible para consumir
             notifyAll();
      
       }//Fin de put
      
}//Fin de Cola

ARCHIVO PRODUCTOR.JAVA

package Actividad26_productorConsumidor1;

public class Productor extends Thread {
      
       private Cola cola;
       private int n;
      
       public Productor(Cola c, int n) {
             cola = c;
             this.n = n;
       }
      
      
       public void run() {
            
             while(true){
                    cola.put(); 
                    try {
                           sleep(100);
                    } catch (InterruptedException e) { } 
             }
            
       }//Fin de run
      
}//Fin de Productor

ARCHIVO CONSUMIDOR.JAVA

package Actividad26_productorConsumidor1;

public class Consumidor extends Thread {
      
       private Cola cola;
       private int n;
      
       public Consumidor(Cola c, int n) {
            
             cola = c;
             this.n = n;
       }
      
      
       public void run() {
            
             int valor = 0;
            
             while(true) {
                   
                    valor = cola.get(); //recoge el número
             }
            
       }//Fin de run
      
}//Fin de Consumidor


ARCHIVO PRODUC_CONSUM.JAVA

package Actividad26_productorConsumidor1;

public class Produc_Consum {
      
       public static void main(String[] args) {
            
             Cola cola = new Cola();
             Productor p = new Productor(cola, 1);
             Consumidor c = new Consumidor(cola, 1);
            
             p.start();
             c.start();
       }
}

2. Modifica la clase Productor para que el constructor reciba un argumento String que será el mensaje que debe enviar a la cola y la clase Consumidor toma la cadena de la cola y la visualice. El programa principal creará dos hilos Productor, uno que escribirá el mensaje "TIC", y otro que escriba el mensaje "TAC".

La salida tiene que mostrar lo siguiente: TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC TIC TAC….

“Refactoriza” el atributo disponible como turnoConsumidor.

ARCHIVO COLA.JAVA

package Actividad26_productorConsumidor2;

import java.util.Stack;

public class Cola {
      
       private int numero;
       private boolean turnoConsumidor = false; //inicialmente cola vacía
       private Stack<String> contenido = new Stack<String>();
       private String resultado;
      
       public synchronized String get() {       
             while(turnoConsumidor == false){ 
                    try{
                           wait();
                    }catch (InterruptedException e){}
             }//fin de while
             resultado = contenido.pop();
             turnoConsumidor=false;
             notifyAll();
             return resultado; //se devuelve
      
       }//Fin de get
      
      
       public synchronized void put(String cadena) {
            
             while (turnoConsumidor == true){
                    try {
                           wait();
                    }catch (InterruptedException e){}
             }
             contenido.push(cadena);
             turnoConsumidor=true; //disponible para consumir
             notifyAll();
      
       }//Fin de put
      
}//Fin de Cola

ARCHIVO PRODUCTOR.JAVA

package Actividad26_productorConsumidor2;

public class Productor extends Thread {
      
       private Cola cola;
       private int n;
       private String cadena;
      
       public Productor(Cola c, int n, String cadena) {
             cola = c;
             this.n = n;
             this.cadena = cadena;
       }
      
       public void run() {
            
             while(true){
                    cola.put(cadena); 
                    try {
                           sleep(100);
                    } catch (InterruptedException e) { } 
             }
            
       }//Fin de run
      
}//Fin de Productor

ARCHIVO CONSUMIDOR.JAVA

package Actividad26_productorConsumidor2;

public class Consumidor extends Thread {
      
       private Cola cola;
       private int n;
       private String r;
      
       public Consumidor(Cola c, int n) {
            
             cola = c;
             this.n = n;
       }
      
      
       public void run() {
            
             while(true) {
                    r = cola.get(); //recoge el número
                    System.out.println(r);
             }
            
       }//Fin de run
      
}//Fin de Consumidor

ARCHIVO PRODUC_CONSUM.JAVA

package Actividad26_productorConsumidor2;

public class Produc_Consum {
      
       public static void main(String[] args) {
            
             Cola cola = new Cola();
             Productor p1 = new Productor(cola, 1, "TIC");
             Productor p2 = new Productor(cola, 1, "TAC");
             Consumidor c = new Consumidor(cola, 1);
            
             p1.start();
             c.start();
             p2.start();
       }
}

3. “Refactoriza” el nombre de la clase Cola por con un nuevo nombre Monitor. Modifica la clase Monitor para que el constructor reciba el número de productores que se van a sincronizar. El programa principal creará 7 hilos Productor, cada uno respectivamente escribirá el nombre de un día de la semana.

ARCHIVO MONITOR.JAVA

package Actividad26_productorConsumidor3;

import java.util.Stack;

public class Monitor {
      
       // Propiedades
       private int numero;
       private boolean turnoConsumidor = false; //inicialmente cola vacía
       private int turnoProductor = 1;
       private Stack<String> contenido = new Stack<String>();
       private String resultado;
       private int contador = 0;
      
       // Constructor
       public Monitor(int numero){
             this.numero = numero;
       }
      
       // Métodos
       public synchronized String get() {       
             while(turnoConsumidor == false){ 
                    try{
                           wait();
                    }catch (InterruptedException e){}
             }//fin de while
             resultado = contenido.pop();
             turnoConsumidor=false;
             notifyAll();
             return resultado; //se devuelve
      
       }//Fin de get
      
       public synchronized void put(String cadena, int turno) {
            
             while (turnoConsumidor == true || turno != turnoProductor){
                    try {
                           wait();
                    }catch (InterruptedException e){}
             }
             if (turno == turnoProductor){
                    contenido.push(cadena);
                    turnoConsumidor=true; //disponible para consumir
                    if (turnoProductor == 7)
                           turnoProductor = 1;
                    else
                           turnoProductor++;
             }
             notifyAll();
       }//Fin de put
      
}//Fin de Cola

ARCHIVO PRODUCTOR.JAVA

package Actividad26_productorConsumidor3;

public class Productor extends Thread {
      
       private Monitor monitor;
       private int n;
       private String cadena;
      
       public Productor(Monitor monitor, int n, String cadena) {
             this.monitor = monitor;
             this.n = n;
             this.cadena = cadena;
       }
      
       public void run() {
            
             while(true){
                    monitor.put(cadena, n); 
                    try {
                           sleep(100);
                    } catch (InterruptedException e) { } 
             }
            
       }//Fin de run
      
}//Fin de Productor

ARCHIVO CONSUMIDOR.JAVA

package Actividad26_productorConsumidor3;

public class Consumidor extends Thread {
      
       private Monitor monitor;
       private int n;
       private String r;
      
       public Consumidor(Monitor monitor, int n) {
            
             this.monitor = monitor;
             this.n = n;
       }
      
      
       public void run() {
            
             while(true) {
                    r = monitor.get(); //recoge el número
            
                           System.out.println(r);
             }
            
       }//Fin de run
      
}//Fin de Consumidor

ARCHIVO PRODUC_CONSUM.JAVA

package Actividad26_productorConsumidor3;

public class Produc_Consum {
      
       public static void main(String[] args) {
            
             Monitor monitor = new Monitor(7);
             Consumidor c = new Consumidor(monitor, 1);
             Productor p1 = new Productor(monitor, 1, "Lunes");
             Productor p2 = new Productor(monitor, 2, "Martes");
             Productor p3 = new Productor(monitor, 3, "Miercoles");
             Productor p4 = new Productor(monitor, 4, "Jueves");
             Productor p5 = new Productor(monitor, 5, "Viernes");
             Productor p6 = new Productor(monitor, 6, "Sabado");
             Productor p7 = new Productor(monitor, 7, "Domingo");
            
             c.start();
             p1.start();
             p2.start();
             p3.start();
             p4.start();
             p5.start();
             p6.start();
             p7.start();
       }
}

4. Modifica el programa principal anterior para que se creen 12 hilos Productor con los nombres de los meses. Si no lo has hecho ya, crea un vector de productores.

ARCHIVO MONITOR.JAVA

package Actividad26_productorConsumidor4;

import java.util.Stack;

public class Monitor {
      
       // Propiedades
       private int numeroProductores = 0;
       private boolean turnoConsumidor = false; //inicialmente cola vacía
       private int turnoProductor = 1;
       private Stack<String> contenido = new Stack<String>();
       private String resultado;
       private int contador = 0;
      
       // Constructor
       public Monitor(int numeroProductores){
             this.numeroProductores = numeroProductores;
       }
      
       // Métodos
       public void setNumProductores(int n){
             this.numeroProductores = n;
       }
      
       public synchronized String get() {       
             while(turnoConsumidor == false){ 
                    try{
                           wait();
                    }catch (InterruptedException e){}
             }//fin de while
             resultado = contenido.pop();
             turnoConsumidor=false;
             notifyAll();
             return resultado; //se devuelve
      
       }//Fin de get
      
       public synchronized void put(String cadena, int turno) {
            
             while (turnoConsumidor == true || turno != turnoProductor){
                    try {
                           wait();
                    }catch (InterruptedException e){}
             }
             if (turno == turnoProductor){
                    contenido.push(cadena);
                    turnoConsumidor=true; //disponible para consumir
                    if (turnoProductor == numeroProductores)
                           turnoProductor = 1;
                    else
                           turnoProductor++;
             }
             notifyAll();
       }//Fin de put
      
}//Fin de Cola

ARCHIVO PRODUCTOR.JAVA

package Actividad26_productorConsumidor4;

public class Productor extends Thread {
      
       private Monitor monitor;
       private int n;
       private String cadena;
      
       public Productor(Monitor monitor, int n, String cadena) {
             this.monitor = monitor;
             this.n = n;
             this.cadena = cadena;
       }
      
       public void run() {
            
             while(true){
                    monitor.put(cadena, n); 
                    try {
                           sleep(100);
                    } catch (InterruptedException e) { } 
             }
            
       }//Fin de run
      
}//Fin de Productor

ARCHIVO CONSUMIDOR.JAVA

package Actividad26_productorConsumidor4;

public class Consumidor extends Thread {
      
       private Monitor monitor;
       private int n;
       private String r;
      
       public Consumidor(Monitor monitor, int n) {
            
             this.monitor = monitor;
             this.n = n;
       }
      
      
       public void run() {
            
             while(true) {
                    r = monitor.get(); //recoge el número
            
                           System.out.println(r);
             }
            
       }//Fin de run
      
}//Fin de Consumidor

ARCHIVO PRODUC_CONSUM.JAVA

package Actividad26_productorConsumidor4;
import java.util.Vector;

public class Produc_Consum {
      
       public static void main(String[] args) {
            
             Monitor monitor = new Monitor(7);
             Vector<Productor> productores = new Vector<Productor>();
             Consumidor c = new Consumidor(monitor, 1);
             productores.addElement(new Productor(monitor, 1, "Enero"));
             productores.addElement(new Productor(monitor, 2, "Febrero"));
             productores.addElement(new Productor(monitor, 3, "Marzo"));
             productores.addElement(new Productor(monitor, 4, "Abril"));
             productores.addElement(new Productor(monitor, 5, "Mayo"));
             productores.addElement(new Productor(monitor, 6, "Junio"));
             productores.addElement(new Productor(monitor, 7, "Julio"));
             productores.addElement(new Productor(monitor, 8, "Agosto"));
             productores.addElement(new Productor(monitor, 9, "Septiembre"));
             productores.addElement(new Productor(monitor, 10, "Octubre"));
             productores.addElement(new Productor(monitor, 11, "Noviembre"));
             productores.addElement(new Productor(monitor, 12, "Diciembre"));
             monitor.setNumProductores(productores.size());
             c.start();
             for (int i = 0; i < productores.size(); i++){
                    productores.elementAt(i).start();
             }
       }

0 comentarios:

Publicar un comentario