Pasar al contenido principal

Práctica 9

Versión para impresiónSend by email

Estudiamos en Java el uso de Monitores para realizar de nuevo el problema del Productor - Consumidor


public class ColaSincronizada {
  
    private int[] Caja;  
    private int Primero, Ultimo, Numero;
    
    public ColaSincronizada(int Longitud) {
      Caja= new int[Longitud];							// Creamos el Buffer
      Primero = 0;								// e inicializamos los contadores
      Ultimo = 0;
      Numero = 0;
    }

    public synchronized void Pon(int X) throws InterruptedException {
      while (Numero == Caja.length) wait();					// mientras este lleno, esperamos
      Caja[Ultimo] = X; 							// introducimos dato en el Buffer
      Ultimo = (Ultimo + 1) % Caja.length;					// y calculamos la siguiente posicion
      ++Numero;									// aumentamos el contador
      notifyAll();								// y notificamos a todos
    }
    
    public synchronized int Toma() throws InterruptedException {
      while (Numero == 0) wait();						// mientras este vacio, esperamos
      int X = Caja[Primero]; 							// sacamos del Buffer
      Primero = (Primero + 1) % Caja.length;					// y calculamos la posicion del dato
      --Numero;									// disminuimos el contador
      notifyAll();								// notificamos a todos
      return X;									// y retornamos el dato
    } 
}

 

public class Productor extends Thread {
    
    ColaSincronizada cs;
    int Id;
    
    public Productor(ColaSincronizada cs, int id) {
      this.cs=cs;
      this.Id=id;
    }
    
    public void run() {
      for (int i=1; i <= 20; i++) 					// 20 veces
        try {
        cs.Pon(i+Id);							// introducimos en Buffer
        System.out.println("---- Productor "+Id+" produce "+(i+Id));	// informamos
        Thread.sleep(Id);						// y esperamos
        } catch (Exception e) {}
      }
}				        				        					 

 

public class Consumidor extends Thread {

    ColaSincronizada cs;
    int Id;
    
    public Consumidor(ColaSincronizada cs, int id) {
      this.cs=cs;
      this.Id=id;
    }
    
    public void run() {
      for (int i=1; i <= 20; i++) 						// 20 veces
        try {
          int Dato=cs.Toma();							// cojo dato del Buffer
          System.out.println("**** Consumidor "+Id+" consume "+Dato);		// informo
          Thread.sleep(Id);							// y me espero
        } 
        catch (Exception e) {}
    }
    
 }

 

public class PC  {
 
    static final int Longitud = 5;
 
    public static void main(String[] args) {
       ColaSincronizada cs= new ColaSincronizada(Longitud);		// creo la cola sincronizada
       Productor p= new Productor(cs, 1000);				// creo el productor
       Consumidor c= new Consumidor(cs, 5000);				// y el consumidor
       p.start();							// y los inicializo
       c.start();
    }
}

Ejecución

merlin1@merlins1:~/Escritorio/Practicas/9$ ls
ColaSincronizada.java Consumidor.java PC.java Productor.java
merlin1@merlins1:~/Escritorio/Practicas/9$ javac PC.java
merlin1@merlins1:~/Escritorio/Practicas/9$ ls
ColaSincronizada.class ColaSincronizada.java Consumidor.class Consumidor.java PC.class PC.java Productor.class
Productor.java
merlin1@merlins1:~/Escritorio/Practicas/9$ java PC
---- Productor 1000 produce 1001
**** Consumidor 5000 consume 1001
---- Productor 1000 produce 1002
---- Productor 1000 produce 1003
---- Productor 1000 produce 1004
---- Productor 1000 produce 1005
**** Consumidor 5000 consume 1002
---- Productor 1000 produce 1006
---- Productor 1000 produce 1007
---- Productor 1000 produce 1008
**** Consumidor 5000 consume 1003
---- Productor 1000 produce 1009
**** Consumidor 5000 consume 1004
**** Consumidor 5000 consume 1005
---- Productor 1000 produce 1010
**** Consumidor 5000 consume 1006
---- Productor 1000 produce 1011
**** Consumidor 5000 consume 1007
---- Productor 1000 produce 1012
**** Consumidor 5000 consume 1008
---- Productor 1000 produce 1013
**** Consumidor 5000 consume 1009
---- Productor 1000 produce 1014
---- Productor 1000 produce 1015
**** Consumidor 5000 consume 1010
**** Consumidor 5000 consume 1011
---- Productor 1000 produce 1016
**** Consumidor 5000 consume 1012
---- Productor 1000 produce 1017
---- Productor 1000 produce 1018
**** Consumidor 5000 consume 1013
**** Consumidor 5000 consume 1014
---- Productor 1000 produce 1019
---- Productor 1000 produce 1020
**** Consumidor 5000 consume 1015
**** Consumidor 5000 consume 1016
**** Consumidor 5000 consume 1017
**** Consumidor 5000 consume 1018
**** Consumidor 5000 consume 1019
**** Consumidor 5000 consume 1020
merlin1@merlins1:~/Escritorio/Practicas/9$

 

Resultados Pedidos:

Explicación del funcionamiento del programa:

Explicación comentada en el código del programa.

 

Lo mismo con un array de un elemento:

Ejecución

merlin1@merlins1:~/Escritorio/Practicas/9$ nano PC.java 
    static final int Longitud = 1;
merlin1@merlins1:~/Escritorio/Practicas/9$ javac PC.java
merlin1@merlins1:~/Escritorio/Practicas/9$ java PC
---- Productor 1000 produce 1001
**** Consumidor 5000 consume 1001
---- Productor 1000 produce 1002
---- Productor 1000 produce 1003
**** Consumidor 5000 consume 1002
**** Consumidor 5000 consume 1003
---- Productor 1000 produce 1004
---- Productor 1000 produce 1005
**** Consumidor 5000 consume 1004
**** Consumidor 5000 consume 1005
---- Productor 1000 produce 1006
---- Productor 1000 produce 1007
**** Consumidor 5000 consume 1006
**** Consumidor 5000 consume 1007
---- Productor 1000 produce 1008
**** Consumidor 5000 consume 1008
---- Productor 1000 produce 1009
**** Consumidor 5000 consume 1009
---- Productor 1000 produce 1010
**** Consumidor 5000 consume 1010
---- Productor 1000 produce 1011
---- Productor 1000 produce 1012
**** Consumidor 5000 consume 1011
**** Consumidor 5000 consume 1012
---- Productor 1000 produce 1013
**** Consumidor 5000 consume 1013
---- Productor 1000 produce 1014
**** Consumidor 5000 consume 1014
---- Productor 1000 produce 1015
---- Productor 1000 produce 1016
**** Consumidor 5000 consume 1015
**** Consumidor 5000 consume 1016
---- Productor 1000 produce 1017
**** Consumidor 5000 consume 1017
---- Productor 1000 produce 1018
---- Productor 1000 produce 1019
**** Consumidor 5000 consume 1018
---- Productor 1000 produce 1020
**** Consumidor 5000 consume 1019
**** Consumidor 5000 consume 1020
merlin1@merlins1:~/Escritorio/Practicas/9$

Aunque aparezca dos veces el productor de forma seguida, se ejecuta primeramente el consumidor, pero como notifica del hueco antes de imprimir el mensaje, Productor se levanta, introduce dato e imprime el mensaje antes de que el consumidor imprima su mensaje.

 

Crear el programa Pipeline.java en el que se creen dos colas sincronizadas iguales perdo de modo que el productor escriba en la primera cola, el consumidor lea de la segunda y la hebra principal lea los enteros de la primera cola y los copie, uno a uno, en la segunda, a toda velocidad. ¿Cuál es el efecto neto de este programa?

 

public class Pipeline  {
 
    static final int Longitud = 5;
 
    public static void main(String[] args) {
       ColaSincronizada cs= new ColaSincronizada(Longitud);
       ColaSincronizada cs2 = new ColaSincronizada(Longitud);
       Productor p= new Productor(cs, 1000);
       Consumidor c= new Consumidor(cs2, 5000);
       p.start();
       c.start();
       try {
          while(true) {
             for(int i = 0; i < 20; i++) {
                 int dato = cs.Toma();
                 cs2.Pon(dato);
             }
          }
       } catch(Exception e) {}

    }
}

 

Ejecución

merlin1@merlins1:~/Escritorio/Practicas/9$ java Pipeline 
**** Consumidor 5000 consume 1001
---- Productor 1000 produce 1001
---- Productor 1000 produce 1002
---- Productor 1000 produce 1003
---- Productor 1000 produce 1004
---- Productor 1000 produce 1005
**** Consumidor 5000 consume 1002
---- Productor 1000 produce 1006
---- Productor 1000 produce 1007
---- Productor 1000 produce 1008
---- Productor 1000 produce 1009
---- Productor 1000 produce 1010
**** Consumidor 5000 consume 1003
---- Productor 1000 produce 1011
---- Productor 1000 produce 1012
---- Productor 1000 produce 1013
---- Productor 1000 produce 1014
**** Consumidor 5000 consume 1004
---- Productor 1000 produce 1015
**** Consumidor 5000 consume 1005
---- Productor 1000 produce 1016
**** Consumidor 5000 consume 1006
---- Productor 1000 produce 1017
**** Consumidor 5000 consume 1007
---- Productor 1000 produce 1018
**** Consumidor 5000 consume 1008
---- Productor 1000 produce 1019
**** Consumidor 5000 consume 1009
---- Productor 1000 produce 1020
**** Consumidor 5000 consume 1010
**** Consumidor 5000 consume 1011
**** Consumidor 5000 consume 1012
**** Consumidor 5000 consume 1013
**** Consumidor 5000 consume 1014
**** Consumidor 5000 consume 1015
**** Consumidor 5000 consume 1016
**** Consumidor 5000 consume 1017
**** Consumidor 5000 consume 1018
**** Consumidor 5000 consume 1019
**** Consumidor 5000 consume 1020
^C merlin1@merlins1:~/Escritorio/Practicas/9$

 

¡Se usan las dos colas! Como se copia toda la cola de entrada en la de salida, primeramente se llena la de salida, pero una vez llena la de salida, el programa de copia se bloquea y el productor continúa introduciendo en la cola de entrada. (Se ha tenido que parar la introducción por que la hebra de copia sigue activa, podría arreglarse poniendo un condicional comprobando con boolean isAlive() si las hebras siguen activas.