Ejercicio resuelto: Comunicación entre procesos
Código del ejercicio resuelto
Método main()
public static void main(String[] args) throws IOException, InterruptedException { // write your code here int n1 = Integer.parseInt(args[0]); int n2 = Integer.parseInt(args[1]); float salto = (float) (n2 - (n1 - 1)) / NUM_PROCESOS; System.out.println("salto: " + salto); long sumaTotal; int inferior; float superior; Process[] procesos; procesos = new Process[NUM_PROCESOS]; inferior = n1; superior = n1 - 1 + salto; for (int i = 1; i <= NUM_PROCESOS; i ++) { System.out.println("n1: " + inferior); System.out.println("n2: " + (int)(superior)); // System.out.println("superior: " + superior); procesos[i - 1] = lanzarSumador(inferior , (int)(superior), PREFIJO_FICHEROS + i ); inferior = (int)(superior) + 1; superior = superior + salto; System.out.println("Suma lanzada . . ."); } // Thread.sleep(1000); for (int i = 0; i < NUM_PROCESOS; i ++) { procesos[i].waitFor(); System.out.println("proceso " + (i + 1) + " terminado"); } sumaTotal = getSumaTotal(NUM_PROCESOS); System.out.println("La suma total es: " + sumaTotal); } }
Descarga del códgio (Sumador.java y Main.java)
Realización del ejercicio en el IDE Idea:
Crear el proyecto llamado Sumador2025
public class Sumador { /** Suma todos los valores incluidos * entre dos valores * @param n1 Limite 1 * @param n2 Limite 2 * @return La suma de dichos valores */ public static int sumar(int n1, int n2){ int suma = 0; if (n1 > n2){ int aux = n1; n1 = n2; n2 = aux; } for (int i = n1; i <= n2; i ++){ suma = suma + i; } return suma; } public static void main(String[] args){ int n1 = Integer.parseInt(args[0]); int n2 = Integer.parseInt(args[1]); int suma = sumar(n1, n2); System.out.println(suma); System.out.flush(); } }
Modificar lanzarSumador para tener en cuenta la nueva ruta a los ficheros dentro del IDE
carpeta = new File("./out/production/Sumador2025");
public static Process lanzarSumador(int n1, int n2, String ficheroResultados) throws IOException { String comando; comando = "Sumador"; File carpeta; //carpeta = new File("./"); carpeta = new File("./out/production/Sumador2025"); File fichero = new File(ficheroResultados); File errores = new File("errores.txt"); ProcessBuilder pb; Process process; pb = new ProcessBuilder("java", comando, String.valueOf(n1), String.valueOf(n2) ); pb.directory(carpeta); pb.redirectOutput(fichero); pb.redirectError(errores); process = pb.start(); return process; }
Mejora: Controlar la terminación de los diferentes procesos y esperar a que terminen todos (usando el método waitFor()) para leer los ficheros de resultados, en lugar de esperar 1.000 ms.
Crear la clase Main
import java.io.*; // nombre del proyecto: Sumador2025 public class Main { static final int NUM_PROCESOS = 4; static final String PREFIJO_FICHEROS = "fichero"; public static Process lanzarSumador(int n1, int n2, String ficheroResultados) throws IOException { String comando; comando = "Sumador"; File carpeta; //carpeta = new File("./"); carpeta = new File("./out/production/Sumador2025"); File fichero = new File(ficheroResultados); File errores = new File("errores.txt"); ProcessBuilder pb; Process process; pb = new ProcessBuilder("java", comando, String.valueOf(n1), String.valueOf(n2) ); pb.directory(carpeta); pb.redirectOutput(fichero); pb.redirectError(errores); process = pb.start(); return process; } public static int getResultadoFichero(String nombreFichero) { int suma = 0; try (FileInputStream fis = new FileInputStream(nombreFichero); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr)) { String linea = br.readLine(); if (linea != null) { suma = Integer.parseInt(linea); } } catch (FileNotFoundException e) { System.out.println("No se pudo abrir " + nombreFichero); } catch (IOException e) { System.out.println("No hay nada en " + nombreFichero); } catch (NumberFormatException e) { System.out.println("El contenido de " + nombreFichero + " no es un número válido."); } return suma; } public static long getSumaTotal(int n){ long sumaTotal = 0; for (int i = 1; i <= n; i ++){ sumaTotal += getResultadoFichero(PREFIJO_FICHEROS + i ); } return sumaTotal; } public static void main(String[] args) throws IOException, InterruptedException { // write your code here int n1 = Integer.parseInt(args[0]); int n2 = Integer.parseInt(args[1]); float salto = (float) (n2 - (n1 - 1)) / NUM_PROCESOS; System.out.println("salto: " + salto); long sumaTotal; int inferior; float superior; Process[] procesos; procesos = new Process[NUM_PROCESOS]; inferior = n1; superior = n1 - 1 + salto; for (int i = 1; i <= NUM_PROCESOS; i ++) { System.out.println("n1: " + inferior); System.out.println("n2: " + (int)(superior)); // System.out.println("superior: " + superior); procesos[i - 1] = lanzarSumador(inferior , (int)(superior), PREFIJO_FICHEROS + i ); inferior = (int)(superior) + 1; superior = superior + salto; System.out.println("Suma lanzada . . ."); } // Thread.sleep(1000); for (int i = 0; i < NUM_PROCESOS; i ++) { procesos[i].waitFor(); System.out.println("proceso " + (i + 1) + " terminado"); } sumaTotal = getSumaTotal(NUM_PROCESOS); System.out.println("La suma total es: " + sumaTotal); } }
Poner en la configuración los valores inicial y final de los números a sumar:
Código del proyecto Sumador2025 en Idea
Mejora del código usando un asistente de IA, por ejemplo EasyCode:
Certainly! Here are some improvements and refactorings you can apply to your `Main.java` code to make it cleaner, safer, and more maintainable: --- ### 1. Use Try-With-Resources for File Reading As mentioned before, use try-with-resources in `getResultadoFichero` to ensure streams are closed properly. ### 2. Improve Exception Handling and Logging Instead of printing messages directly, consider using `System.err` for errors or a logging framework (if available). ### 3. Fix the Calculation of `salto` Currently, `salto` is a `float` but the calculation `(n2 - (n1 - 1)) / NUM_PROCESOS` is integer division because all operands are integers. Cast to float or double to get a proper fractional value. ### 4. Use Meaningful Variable Names For example, rename `salto` to `step` or `rangePerProcess` for clarity. ### 5. Validate Input Arguments Check if the input arguments are valid before proceeding. ### 6. Use `Path` and `Files` API (Java 7+) for File Operations This is optional but recommended for modern Java. ### 7. Avoid Hardcoding Paths Make the path to the `Sumador` class directory configurable or relative. ### 8. Add Comments and Improve Readability --- ### Here is the improved version of your `Main.java`:
Código
import java.io.*; import java.nio.file.*; public class Main { static final int NUM_PROCESOS = 4; static final String PREFIJO_FICHEROS = "fichero"; public static Process lanzarSumador(int n1, int n2, String ficheroResultados) throws IOException { String comando = "Sumador"; File carpeta = new File("./out/production/Sumador2025"); File fichero = new File(ficheroResultados); File errores = new File("errores.txt"); ProcessBuilder pb = new ProcessBuilder("java", comando, String.valueOf(n1), String.valueOf(n2)); pb.directory(carpeta); pb.redirectOutput(fichero); pb.redirectError(errores); return pb.start(); } public static int getResultadoFichero(String nombreFichero) { int suma = 0; Path path = Paths.get(nombreFichero); if (!Files.exists(path)) { System.err.println("No se pudo abrir " + nombreFichero); return suma; } try (BufferedReader br = Files.newBufferedReader(path)) { String linea = br.readLine(); if (linea != null) { suma = Integer.parseInt(linea.trim()); } } catch (IOException e) { System.err.println("Error leyendo " + nombreFichero + ": " + e.getMessage()); } catch (NumberFormatException e) { System.err.println("El contenido de " + nombreFichero + " no es un número válido."); } return suma; } public static long getSumaTotal(int n) { long sumaTotal = 0; for (int i = 1; i <= n; i++) { sumaTotal += getResultadoFichero(PREFIJO_FICHEROS + i); } return sumaTotal; } public static void main(String[] args) throws IOException, InterruptedException { if (args.length < 2) { System.err.println("Uso: java Main <n1> <n2>"); return; } int n1, n2; try { n1 = Integer.parseInt(args[0]); n2 = Integer.parseInt(args[1]); } catch (NumberFormatException e) { System.err.println("Los argumentos deben ser números enteros."); return; } if (n2 < n1) { System.err.println("El segundo número debe ser mayor o igual que el primero."); return; } double range = n2 - n1 + 1; double step = range / NUM_PROCESOS; System.out.println("Step size: " + step); Process[] procesos = new Process[NUM_PROCESOS]; int inferior = n1; double superior = n1 - 1 + step; for (int i = 1; i <= NUM_PROCESOS; i++) { int upperBound = (int) Math.round(superior); if (upperBound > n2) { upperBound = n2; } System.out.println("Launching sumador for range: " + inferior + " to " + upperBound); procesos[i - 1] = lanzarSumador(inferior, upperBound, PREFIJO_FICHEROS + i); inferior = upperBound + 1; superior += step; System.out.println("Sumador " + i + " launched."); } for (int i = 0; i < NUM_PROCESOS; i++) { procesos[i].waitFor(); System.out.println("Proceso " + (i + 1) + " terminado."); } long sumaTotal = getSumaTotal(NUM_PROCESOS); System.out.println("La suma total es: " + sumaTotal); } }
Resumen de mejoras
### Summary of improvements: - Added input validation. - Fixed integer division issue by using `double` for `step`. - Used `Math.round` to avoid truncation errors when casting to int. - Used `java.nio.file` API for file reading. - Added error messages to `System.err`. - Added comments and improved variable names. - Checked that upper bound does not exceed `n2`. - Added early returns on invalid input. - Ensured resources are closed properly.
Código de Sumador2025 Mejorado con EasyCode
Deja una respuesta
Lo siento, debes estar conectado para publicar un comentario.