Hilos en Java: Conceptos Avanzados y Ejercicio Complejo

La programación multihilo es una de las habilidades más desafiantes y útiles en el desarrollo de aplicaciones modernas. Este artículo explora los conceptos avanzados de hilos en Java y presenta un ejercicio práctico para poner a prueba tus conocimientos en programación concurrente.


Conceptos Clave para Trabajar con Hilos en Java

Sincronización de Recursos Compartidos

Cuando varios hilos acceden a un recurso compartido, como una lista o una variable, es crucial usar mecanismos de sincronización para evitar condiciones de carrera. Java ofrece herramientas como synchronized, wait(), notify(), y clases avanzadas como ReentrantLock.

Comunicación entre Hilos

La comunicación entre hilos permite que un hilo espere a que otro complete su tarea. Esto se logra utilizando los métodos wait(), notify(), y notifyAll() en combinación con bloques sincronizados.

Gestión Avanzada de Hilos

Además de las herramientas básicas, Java proporciona el framework ExecutorService para gestionar grandes cantidades de hilos de manera eficiente, junto con herramientas como Callable, Future, y CompletableFuture para manejar tareas con resultados.


Ejercicio: Simulación de una Fábrica Multihilo con Productores y Consumidores

Enunciado

Diseña un programa en Java que simule el funcionamiento de una fábrica con múltiples estaciones de producción y ensamblaje. En esta fábrica:

  1. Estaciones de producción: Generan piezas que se almacenan en un buffer compartido (almacén).
  2. Estaciones de ensamblaje: Toman piezas del buffer para construir un producto.

El sistema debe garantizar que:

  • Las estaciones de ensamblaje no intenten tomar piezas si el buffer está vacío.
  • Las estaciones de producción no sobrecarguen el buffer si está lleno.
  • Los accesos al buffer estén sincronizados para evitar condiciones de carrera.

Requisitos Técnicos

  1. Clases necesarias:
    • Una clase Buffer que represente el almacén compartido.
    • Una clase Productor que genere piezas y las almacene en el buffer.
    • Una clase Consumidor que retire piezas del buffer para ensamblar productos.
  2. Sincronización:
    • Usa wait() y notifyAll() para coordinar los accesos al buffer.
  3. Simulación:
    • Crea 3 productores y 2 consumidores.
    • Cada productor genera 10 piezas.
    • Cada consumidor ensambla productos hasta que no queden piezas en el buffer.

Implementación

import java.util.LinkedList;
import java.util.Queue;

class Buffer {
    private final Queue<Integer> buffer = new LinkedList<>();
    private final int capacidad;

    public Buffer(int capacidad) {
        this.capacidad = capacidad;
    }

    public synchronized void producir(int pieza) throws InterruptedException {
        while (buffer.size() == capacidad) {
            wait(); // Espera si el buffer está lleno
        }
        buffer.add(pieza);
        System.out.println(Thread.currentThread().getName() + " produjo: " + pieza);
        notifyAll(); // Notifica a los consumidores
    }

    public synchronized int consumir() throws InterruptedException {
        while (buffer.isEmpty()) {
            wait(); // Espera si el buffer está vacío
        }
        int pieza = buffer.poll();
        System.out.println(Thread.currentThread().getName() + " consumió: " + pieza);
        notifyAll(); // Notifica a los productores
        return pieza;
    }
}

class Productor implements Runnable {
    private final Buffer buffer;

    public Productor(Buffer buffer) {
        this.buffer = buffer;
    }

    @Override
    public void run() {
        try {
            for (int i = 1; i <= 10; i++) {
                buffer.producir(i);
                Thread.sleep(500); // Simula tiempo de producción
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

class Consumidor implements Runnable {
    private final Buffer buffer;

    public Consumidor(Buffer buffer) {
        this.buffer = buffer;
    }

    @Override
    public void run() {
        try {
            for (int i = 1; i <= 15; i++) {
                buffer.consumir();
                Thread.sleep(1000); // Simula tiempo de ensamblaje
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

public class Fabrica {
    public static void main(String[] args) {
        Buffer buffer = new Buffer(5); // Buffer con capacidad máxima de 5 piezas

        // Crear y ejecutar 3 productores
        for (int i = 1; i <= 3; i++) {
            new Thread(new Productor(buffer), "Productor-" + i).start();
        }

        // Crear y ejecutar 2 consumidores
        for (int i = 1; i <= 2; i++) {
            new Thread(new Consumidor(buffer), "Consumidor-" + i).start();
        }
    }
}

Requisitos de Salida

El programa debe mostrar mensajes similares a estos (el orden puede variar debido a la concurrencia):

Productor-1 produjo: 1
Productor-2 produjo: 2
Productor-3 produjo: 3
Consumidor-1 consumió: 1
Productor-1 produjo: 4
Consumidor-2 consumió: 2
Consumidor-1 consumió: 3
Productor-2 produjo: 5
...

Conceptos Evaluados

  1. Sincronización: Uso correcto de synchronized, wait() y notifyAll() para evitar conflictos.
  2. Manejo de recursos compartidos: El buffer debe funcionar correctamente bajo concurrencia.
  3. Gestión eficiente de hilos: Creación y ejecución de múltiples productores y consumidores.

Resumen

Este ejercicio combina conceptos fundamentales y avanzados de programación multihilo, como sincronización, gestión de recursos compartidos y coordinación entre hilos. Practicar este tipo de problemas te ayudará a dominar las habilidades necesarias para implementar sistemas concurrentes robustos y eficientes.

black screen with code
Photo by Antonio Batinić on Pexels.com

Deja un comentario

Información básica sobre protección de datos Ver más

  • Responsable: Tomas Gonzalez.
  • Finalidad:  Moderar los comentarios.
  • Legitimación:  Por consentimiento del interesado.
  • Destinatarios y encargados de tratamiento:  No se ceden o comunican datos a terceros para prestar este servicio.
  • Derechos: Acceder, rectificar y suprimir los datos.
  • Información Adicional: Puede consultar la información detallada en la Política de Privacidad.

error: Content is protected !!

Descubre más desde Tomás González: Formador y Desarrollador Web

Suscríbete ahora para seguir leyendo y obtener acceso al archivo completo.

Seguir leyendo

Este sitio web utiliza cookies, si necesitas más información puedes visitar nuestra política de privacidad    Ver
Privacidad