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

Añadir la clase Sumador

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