Untitled - JAVA 5.21 KB
                                
                                    import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.*;

public class ProcessRunner implements Runnable {
    private ProcessBuilder processBuilder;
    private volatile Exception threadException; // Wyjątek przechowywany w tle, musi być volatile

    public ProcessRunner(ProcessBuilder processBuilder) {
        this.processBuilder = processBuilder;
    }

    @Override
    public void run() {
        try {
            Process process = processBuilder.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            
            // Logi wyjściowe działające w tle
            new Thread(() -> {
                String line;
                try {
                    while ((line = reader.readLine()) != null) {
                        System.out.println("LOG: " + line);
                    }
                } catch (IOException e) {
                    System.err.println("Error reading log: " + e.getMessage());
                }
            }).start();
            
            // Odczytywanie błędów i zapisywanie, ale nie przerywamy procesu
            String errorLine;
            while ((errorLine = errorReader.readLine()) != null) {
                System.err.println("ERROR: " + errorLine);
                threadException = new RuntimeException("Error detected in process: " + errorLine);
            }

            int exitCode = process.waitFor(); // Czekamy aż proces się zakończy
            if (exitCode != 0) {
                threadException = new RuntimeException("Process finished with non-zero exit code: " + exitCode);
            }

        } catch (IOException | InterruptedException e) {
            threadException = e;
        }
    }

    public Exception getThreadException() {
        return threadException;
    }
}

// Klasa główna
public class MainApp {
    public static void main(String[] args) {
        // Tworzymy ExecutorService z pulą wątków
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        // Tworzymy ProcessBuilder dla naszej aplikacji
        ProcessBuilder processBuilder = new ProcessBuilder("path_to_exe", "arg1", "arg2");

        // Tworzymy obiekt ProcessRunner
        ProcessRunner processRunner = new ProcessRunner(processBuilder);

        // Składamy zadanie do wykonania w tle
        executorService.submit(processRunner);

        // Główna pętla, sprawdzająca stan procesu w tle co pewien czas
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        scheduler.scheduleAtFixedRate(() -> {
            Exception e = processRunner.getThreadException();
            if (e != null) {
                System.err.println("Error caught from process: " + e.getMessage());
                // Obsługa błędów, ale proces nadal działa
            }
        }, 0, 1, TimeUnit.SECONDS); // Sprawdzanie co sekundę

        // Proces w tle działa, a główny wątek kontynuuje swoje działanie
        System.out.println("Main thread continues while process runs in the background.");

        // Upewnij się, że ExecutorService i Scheduler zostaną poprawnie zakończone
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            executorService.shutdown();
            scheduler.shutdown();
        }));
    }
}

Kluczowe punkty rozwiązania:
Proces działa równolegle: ExecutorService uruchamia proces w oddzielnym wątku, a ScheduledExecutorService sprawdza co pewien czas, czy wystąpił błąd.

Raportowanie błędów bez zatrzymywania procesu: Wątek z procesem może raportować błędy, ale nie przerywa swojego działania. Główna pętla (za pomocą ScheduledExecutorService) sprawdza, czy w procesie pojawił się błąd i odpowiednio go obsługuje.

Błędy są zgłaszane w tle: W przypadku wystąpienia błędu, wyjątek jest przechwytywany i można go obsłużyć (np. logować, wysyłać powiadomienia) bez zatrzymywania procesu.

Proces działa niezależnie: Proces działa w tle bez ingerencji w główny wątek. Główny wątek aplikacji może działać normalnie, niezależnie od procesu w tle.

Dodatkowe informacje:
ScheduledExecutorService jest używany do okresowego sprawdzania, czy w procesie pojawił się błąd.
volatile: Zmienna threadException jest oznaczona jako volatile, aby zapewnić poprawną widoczność zmiany wartości między wątkami.
Shutdown: Runtime.getRuntime().addShutdownHook dodaje hook, który zamyka ExecutorService i Scheduler podczas zamykania aplikacji, zapewniając poprawne zakończenie wszystkich wątków.
To podejście spełnia Twoje wymagania: proces działa w tle, błędy są zgłaszane, a proces nie zostaje przerwany w momencie wystąpienia błędu.
                                
                            

Paste Hosted With By Wklejamy.pl