Cliente – Suministrador con Idea
Ejercicio Productor – Consumidor resuelto con IntelliJ Idea 2022.3
El proyecto se llama Cliente-Suministrador
Constantes.java
public class Constantes { public static final String FICHEROLOG = "ficheroLog.txt"; public static final String INTERCAMBIO = "numeros.txt"; public static final String FICHEROERRORES = "errores.txt"; public static final int REPETICIONES = 10; //El proyecto se llama Cliente-Suministrador public static final String CARPETA = "./out/production/Cliente-Suministrador/"; }
Suministrador.java
public class Suministrador { public static void main(String[] args) throws IOException { int cuenta = 0; FileLock bloqueo = null; RandomAccessFile raf = null; //Rediregimos la salida y error estándar al fichero de log try { PrintStream ps = new PrintStream(new BufferedOutputStream(new FileOutputStream(new File(Constantes.FICHEROLOG),true)), true); System.setOut(ps); System.setErr(ps); } catch (FileNotFoundException exp) { System.out.println(exp.getCause()); exp.printStackTrace(); } while (cuenta <= Constantes.REPETICIONES) { try { raf = new RandomAccessFile(Constantes.INTERCAMBIO, "rwd"); //Abrimos el fichero //Sección crítica bloqueo = raf.getChannel().lock(); System.out.println("Suministrador: Entra en la sección"); if (raf.length() == 0) { int aleatorio = generarNumeroAleatorioEntre(1, 100); raf.writeInt(aleatorio); System.out.println("Suministrador: dato escrito " + aleatorio); cuenta ++; } else System.out.println("Suministrador: no puede escribir"); System.out.println("Suministrador: Sale de la sección"); bloqueo.release(); bloqueo = null; //Fin sección crítica Thread.sleep(1000); //Simulamos tiempo de creación del dato } catch (Exception e) { System.err.println("Suministrador. Error al acceder al fichero."); System.err.println(e.toString()); } finally { try { if (bloqueo != null) bloqueo.release(); if (raf != null) raf.close(); } catch (IOException exp4) { System.out.println(exp4.getCause()); exp4.printStackTrace(); } } } System.out.println("Suministrador: FIN"); } private static int generarNumeroAleatorioEntre(int minimo, int maximo) { return (int) (Math.random() * (maximo + 1 - minimo)) + minimo; } }
Cliente.java
public class Cliente { /** * @param args Argumento [0] da el número de cliente, lo recibe al lanzarlo con ProcessBuilder */ public static void main(String[] args) { int numeroCliente = Integer.parseInt(args[0]); RandomAccessFile raf = null; FileLock bloqueo = null; int cuenta = 1; int valor; //Rediregimos salida y error estándar a un fichero PrintStream ps = null; try { ps = new PrintStream(new BufferedOutputStream(new FileOutputStream(new File(Constantes.FICHEROLOG),true)), true); System.setOut(ps); System.setErr(ps); } catch (FileNotFoundException exp) { System.out.println(exp.getCause()); exp.printStackTrace(); } while (cuenta <= Constantes.REPETICIONES) {// Leemos del fichero las repeticiones realizadas por el suministrador try { raf = new RandomAccessFile(Constantes.INTERCAMBIO, "rwd"); //Abrimos el fichero //Sección crítica bloqueo = raf.getChannel().lock(); System.out.println("Cliente " + numeroCliente + ": entra en la sección"); if (raf.length() > 0) { valor = raf.readInt(); System.out.println("Cliente " + numeroCliente + ": lee " + valor); raf.setLength(0); cuenta ++; } else System.out.println("Cliente: " + numeroCliente + ": no puede leer"); System.out.println("Cliente " + numeroCliente + " sale de la sección"); bloqueo.release(); bloqueo = null; //Fin sección crítica Thread.sleep(2000);//simulamos tiempo de procesamiento del dato } catch (IOException e) { System.err.println("Cliente " + numeroCliente + ": Error al acceder al fichero."); System.err.println(e.toString()); } catch (OverlappingFileLockException ex) { System.err.println("Cliente " + numeroCliente + ": Error en el bloqueo del fichero."); System.err.println(ex.toString()); } catch (InterruptedException e) { e.printStackTrace(); } finally { try { if (bloqueo != null) bloqueo.release(); if (raf != null) raf.close(); } catch (Exception e2) { System.err.println("Cliente " + numeroCliente + ": Error al cerrar el fichero."); System.err.println(e2.toString()); System.exit(1); //Si hay error, finalizamos } } } System.out.println("Cliente " + numeroCliente + " FIN"); } }
Main.java
public class Main { public static void main(String[] args) { //fecha usada para el log de salida Date fecha = new Date(); SimpleDateFormat formato = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); String hora = formato.format(fecha); // La lista de los procesos y los contadores ArrayList<Process> listaProcesos = new ArrayList<>(); int suministrador = 0; int cliente = 0; try {// Eliminamos el contenido del fichero al entrar por si tiene un 0 RandomAccessFile fichero = new RandomAccessFile(Constantes.CARPETA + Constantes.INTERCAMBIO, "rwd"); fichero.setLength(0); fichero.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //Rediregimos salida y error estándar a un fichero, si no la salida de todos los procesos se mezclaría con el menú try { PrintStream ps = new PrintStream(new BufferedOutputStream(new FileOutputStream(new File(Constantes.CARPETA + Constantes.FICHEROLOG),false)), true); ps.println("-----------------" + hora + "-----------------------"); } catch (FileNotFoundException exp) { System.out.println(exp.getCause()); exp.printStackTrace(); } int opcion = 0; do { opcion = mostrarMenuPrincipal(); // Ménu de opciones switch (opcion) { case 1: if (suministrador == 0) { //el suministrador solo se puede lazar una vez listaProcesos.add(lanzadorProcesos("Suministrador", 1)); suministrador ++; System.out.println("Suministrador " + suministrador + " lanzado"); } else{ System.out.println("Solo se puede lanzar un Suministrador y ya hay uno ejecutándose"); } break; case 2: cliente ++; listaProcesos.add(lanzadorProcesos("Cliente", cliente)); System.out.println("Cliente " + cliente + " lanzado"); break; case 3: try { esperarFinalizacion(listaProcesos); } catch (InterruptedException e) { System.out.println(e.getMessage()); } System.out.println("... procesos finalizados"); System.out.println("Ejecuci\u00f3n finalizada"); break; } } while (opcion != 3); } /** * Menú principal de opciones * @return */ private static int mostrarMenuPrincipal() { int opcion = 1; boolean leido = false; int numero = 0; Scanner teclado = null; System.out.println ( "\nSeleccione una opci\u00f3n:" + "\n1. Lanzar Suministrador" + "\n2. Lanzar Cliente" + "\n3. Terminar" + "\nIndique un número del 1 al 3:" ); do { try { teclado = new Scanner(System.in); opcion = teclado.nextInt(); leido = true; } catch (Exception e) { System.out.println("Error: No es un número entero válido.\n"); } } while (!leido); return opcion; } /** * Lanzador de procesos que recibe de entrada un comando y un número usado para diferenciarlos. * Ejecuta el comando y devuelve un proceso. */ public static Process lanzadorProcesos(String comando, int n) { ProcessBuilder pb ; Process process = null; try { pb = new ProcessBuilder("java", comando, String.valueOf(n)); pb.directory(new File(Constantes.CARPETA)); pb.redirectError(new File(Constantes.CARPETA + Constantes.FICHEROERRORES)); process = pb.start(); } catch (IOException e) { e.printStackTrace(); } return process; } /** * Recibe una lista de procesos y espera hasta que todos estan cerrados para devolver true * @param listaProcesos array Process */ private static void esperarFinalizacion(ArrayList<Process> listaProcesos) throws InterruptedException { System.out.print("Procesos en ejecución:\n"); boolean fin = false; int contador = 0; if (listaProcesos.size() > 0) while (!fin) { contador = 0; for (Process proceso : listaProcesos) { if (proceso.isAlive()) { System.out.println(proceso.info()); contador ++; System.out.println(contador); proceso.waitFor(); // Esperar a que termine el proceso } if (contador == 0) fin = true; } Thread.sleep(1000); } } }
Para ver en tiempo real el contenido del fichero de log se puede usar en consola el comando tail:
tail -f out/production/Cliente-Suministrador/ficheroLog.txt
Código del Cliente-Suministrador con IntelliJ Idea
Deja una respuesta
Lo siento, debes estar conectado para publicar un comentario.