Enunciado
Diseña un programa en Java que simule el funcionamiento de un restaurante donde múltiples clientes llegan y son atendidos por meseros. El restaurante tiene un número limitado de mesas, por lo que los clientes deben esperar si no hay mesas disponibles. Los meseros deben coordinarse para atender a los clientes de manera ordenada.
Requisitos
- Clases necesarias:
- Una clase
Restaurante
que gestione las mesas disponibles. - Una clase
Cliente
que represente a los hilos que intentan ocupar mesas. - Una clase
Mesero
que represente a los hilos que atienden a los clientes.
- Una clase
- Gestión del restaurante:
- El restaurante tiene un número limitado de mesas.
- Los clientes deben esperar si no hay mesas libres.
- Cada cliente ocupa una mesa, espera un tiempo mientras come y luego libera la mesa.
- Los meseros atienden a los clientes asignados a las mesas.
- Sincronización:
- Usa
wait()
ynotify()
para coordinar el acceso a las mesas.
- Usa
- Simulación:
- Crea 5 mesas.
- Genera 10 clientes y 2 meseros.
Implementación
import java.util.LinkedList;
import java.util.Queue;
class Restaurante {
private final int capacidadMesas;
private final Queue<Integer> mesasOcupadas = new LinkedList<>();
public Restaurante(int capacidadMesas) {
this.capacidadMesas = capacidadMesas;
}
public synchronized int ocuparMesa() throws InterruptedException {
while (mesasOcupadas.size() == capacidadMesas) {
System.out.println(Thread.currentThread().getName() + " espera por una mesa.");
wait(); // Espera si todas las mesas están ocupadas
}
int numeroMesa = mesasOcupadas.size() + 1;
mesasOcupadas.add(numeroMesa);
System.out.println(Thread.currentThread().getName() + " ocupó la mesa " + numeroMesa);
notifyAll(); // Notifica a los meseros
return numeroMesa;
}
public synchronized void liberarMesa(int numeroMesa) {
mesasOcupadas.remove(numeroMesa);
System.out.println(Thread.currentThread().getName() + " liberó la mesa " + numeroMesa);
notifyAll(); // Notifica a los clientes que esperan por una mesa
}
}
class Cliente implements Runnable {
private final Restaurante restaurante;
public Cliente(Restaurante restaurante) {
this.restaurante = restaurante;
}
@Override
public void run() {
try {
int mesa = restaurante.ocuparMesa();
System.out.println(Thread.currentThread().getName() + " está comiendo en la mesa " + mesa);
Thread.sleep((int) (Math.random() * 3000 + 1000)); // Simula el tiempo de comida
restaurante.liberarMesa(mesa);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
class Mesero implements Runnable {
private final Restaurante restaurante;
public Mesero(Restaurante restaurante) {
this.restaurante = restaurante;
}
@Override
public void run() {
try {
while (true) {
System.out.println(Thread.currentThread().getName() + " está verificando las mesas.");
Thread.sleep(2000); // Simula tiempo de servicio
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public class SimulacionRestaurante {
public static void main(String[] args) {
Restaurante restaurante = new Restaurante(5); // 5 mesas disponibles
// Crear e iniciar hilos de clientes
for (int i = 1; i <= 10; i++) {
new Thread(new Cliente(restaurante), "Cliente-" + i).start();
}
// Crear e iniciar hilos de meseros
for (int i = 1; i <= 2; i++) {
new Thread(new Mesero(restaurante), "Mesero-" + i).start();
}
}
}
Requisitos de Salida
El programa debe mostrar mensajes como los siguientes:
Cliente-1 ocupó la mesa 1
Cliente-1 está comiendo en la mesa 1
Cliente-2 ocupó la mesa 2
Cliente-3 espera por una mesa.
Cliente-1 liberó la mesa 1
Cliente-3 ocupó la mesa 1
Mesero-1 está verificando las mesas.
...
Conceptos Evaluados
- Sincronización: Uso de
synchronized
,wait()
ynotifyAll()
para gestionar recursos compartidos (mesas). - Gestión de concurrencia: Manejo de múltiples clientes y meseros de forma concurrente.
- Coordinación de hilos: Garantizar que los clientes y meseros trabajen de manera coordinada.
Resumen
Este ejercicio combina el manejo de hilos, sincronización y coordinación en un escenario práctico. Practicar con simulaciones similares te ayudará a entender cómo aplicar estos conceptos en sistemas concurrentes del mundo real.