Subido por Antonio Jiménez (Toño)

Producto-Consumidor

Anuncio
Producto-Consumidor
Integrantes:
Daimery Quintero González
José Antonio Jimenes Corona
Introducción:
¿Qué es el Algoritmo Producto Consumidor?
El algoritmo de "producto-consumidor" es un patrón de programación concurrente o
concurrencia utilizado para la comunicación y la sincronización entre procesos o hilos en
un programa. Se usa comúnmente para resolver problemas relacionados con la gestión de
recursos compartidos entre varios hilos o procesos.
Análisis de Programa
El escenario típico que ilustra este algoritmo involucra dos roles: el "productor" y el
"consumidor". Los productores son responsables de generar datos o elementos, que luego
se almacenan en una estructura de datos compartida, mientras que los consumidores
retiran esos datos de la estructura compartida. La idea es que los productores y
consumidores trabajen en paralelo de manera eficiente y sincronizada
Clase Buffer:
buffer[]: Un arreglo de caracteres que representa el buffer compartido.
siguiente: Un índice que sigue el próximo lugar disponible en el buffer.
estaLlena y estaVacia: Banderas que indican si el buffer está lleno o vacío,
respectivamente.
El constructor inicializa las variables y el arreglo.
Método consumir():
Este método es sincronizado (synchronized), lo que significa que se puede acceder a él de
manera segura desde múltiples hilos.
Utiliza un bucle while para esperar si el buffer está vacío. Si está vacío, el hilo consumidor
espera utilizando wait() hasta que un productor notifique que hay datos disponibles.
Cuando el buffer no está vacío, se decrementa el índice siguiente, se recoge el valor en ese
índice y se actualizan las banderas de estado (estaLlena y estaVacia).
Finalmente, se notifica a todos los hilos para que puedan continuar o, en caso de que haya
más consumidores esperando, uno de ellos pueda tomar el recurso.
Método producir(char c):
Este método también es sincronizado y opera de manera similar al método consumir().
Espera si el buffer está lleno y, una vez que hay espacio disponible, coloca el carácter c en
el buffer, actualiza el índice y las banderas de estado, y notifica a otros hilos.
Clase Productor:
Extiende la clase Thread y representa un hilo productor.
En su método run(), el productor genera caracteres aleatorios y llama al método producir()
del buffer compartido para depositar esos caracteres.
Luego, espera un tiempo aleatorio antes de continuar.
Clase Consumidor:
Al igual que la clase Productor, esta clase extiende Thread y representa un hilo
consumidor.
En su método run(), el consumidor llama al método consumir() del buffer compartido para
recoger caracteres.
También espera un tiempo aleatorio antes de continuar.
Clase EjemploProductorConsumidor:
El método main crea una instancia de la clase Buffer y dos hilos, uno para el productor y
otro para el consumidor.
Luego, inicia ambos hilos, lo que permite que la producción y el consumo de caracteres
ocurran en paralelo.
Código:
//Daimery Quintero Gonzalez
public class Buffer {
private char buffer[];
private int siguiente;
private boolean estaLlena;
private boolean estaVacia;
public Buffer(int tamanio) {
buffer = new char[tamanio];
siguiente = 0;
estaLlena = false;
estaVacia = true;
}
public synchronized char consumir() {
while (estaVacia) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
siguiente--;
char valor = buffer[siguiente];
estaLlena = false;
estaVacia = siguiente == 0;
notifyAll();
return valor;
}
public synchronized void producir(char c) {
while (estaLlena) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
buffer[siguiente] = c;
siguiente++;
estaLlena = siguiente == buffer.length;
estaVacia = false;
notifyAll();
}
}
public class Productor extends Thread {
private Buffer buffer;
private final String letras = "abcdefghijklmnopqrstuvxyz";
public Productor(Buffer buffer) {
this.buffer = buffer;
}
public void run() {
while (true) {
char c = letras.charAt((int) (Math.random() * letras.length()));
buffer.producir(c);
System.out.println("Depositado el caracter " + c + " en el buffer");
try {
sleep((int) (Math.random() * 4000));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
public class Consumidor extends Thread {
private Buffer buffer;
public Consumidor(Buffer buffer) {
this.buffer = buffer;
}
public void run() {
while (true) {
char valor = buffer.consumir();
System.out.println("Recogido el caracter " + valor + " del buffer");
try {
sleep((int) (Math.random() * 4000));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
public class EjemploProductorConsumidor {
public static void main(String[] args) {
Buffer b = new Buffer(10);
Productor p = new Productor(b);
Consumidor c = new Consumidor(b);
p.start();
c.start();
}
}
Ejecución:
Conclusión:
En resumen, el programa ejemplifica la implementación del patrón de programación
productor-consumidor en Java para gestionar la comunicación y la sincronización entre
múltiples hilos en un entorno de concurrencia. Utiliza métodos sincronizados y estructuras
de datos compartidas para asegurar un acceso seguro y coordinado a recursos compartidos.
Esto ilustra la importancia de la sincronización en la programación concurrente y cómo
abordar problemas de concurrencia de manera efectiva.
Descargar