2016-11-01 4 views
0

У меня есть класс, который действует как родительский процесс. Во время своего запуска он создает много дочерних процессов и запускает их одновременно. Каждый дочерний процесс - это в основном HTTP-клиент, который подключается к службе и извлекает данные из нее.связь между родительским процессом и дочерним процессом

В настоящее время, если один из дочерних процессов перестает работать по какой-либо причине, родительский процесс восстанавливает соединение путем перезапуска этого же дочернего процесса.

Отключение дочернего процесса может быть вызвано несколькими вещами. Я хотел бы сообщить причину отключения от дочернего процесса к родительскому процессу и привести к тому, что родительский процесс действует соответственно причине отказа (сбой чтения сокета, 404 не найден, 401 несанкционирован и т. Д.).

Возможно ли это? Какой был бы самый короткий/лучший способ сделать это? Вот мой родительский класс:

public class Parent { 
public static void main(String[] args){ 
    List<Process> PRlist = new ArrayList<Process>(); 
    List<String[]> commandsList = new ArrayList<String[]>(); 
    DateTimeFormatter frmt = DateTimeFormatter.ofPattern("hh:mm:ss"); 

    if (args.length == 2 && args[0].matches("-f")){ 
     String dir = System.getProperty("user.dir"); 
     String path = dir + "/" + args[1]; 
     try { 
      FileReader fr = new FileReader(path); 
      BufferedReader bf = new BufferedReader(fr); 

      String line = ""; 
      while ((line = bf.readLine()) != null){ 
       String[] tk = line.split(" "); 
       String[] cmd = {"java", "-jar", "Child.jar", "-a", tk[0], "-p", tk[1], 
         "-u", tk[2], "-pw", tk[3], "-m", tk[4], "-s", tk[5]}; 
       Process pr = new ProcessBuilder().inheritIO().command(cmd).redirectInput(Redirect.INHERIT).start(); 
       PRlist.add(pr); commandsList.add(cmd); 
      } 
     } 
     catch (FileNotFoundException ex) {ex.printStackTrace();} 
     catch (IOException ex) {ex.printStackTrace();} 

     int streamnum = PRlist.size(); 

     while (true){ 
      for (int i = 0; i < streamnum; i++){ 
       if (!PRlist.get(i).isAlive()){ 
        PRlist.get(i).destroy(); 
        PRlist.remove(i); 
        try { 
         Process PR = new ProcessBuilder().inheritIO().command(commandsList.get(i)).redirectInput(Redirect.INHERIT).start(); 
         System.out.println(commandsList.get(i)[12] + " stream re-established at " + LocalDateTime.now().format(frmt)); 
         PRlist.add(i,PR); 
        } catch (IOException ex) {ex.printStackTrace();} 
       } 
      } 

      try { 
       Thread.sleep(5000); 
      } catch (InterruptedException ex) {ex.printStackTrace();} 
     } 
    } else { 
     System.out.println("No stream file was specified."); 
    } 
}} 

Любая помощь будет оценена.

+0

Есть ли причина, по которой вы используете отдельные экземпляры JVM вместо потоков Java? Это будет более эффективно с точки зрения памяти и намного легче решить вашу проблему. –

+0

+1 к @BorisShchegolev. Если у вас нет очень интересных аргументов, вам действительно нужно делать это с помощью ExecutorService и собирать необходимую информацию через Будущее. – lscoughlin

+0

@BorisShchegolev Я только что написал это с самого начала, никакой особой причины. Если я изменю процессы o потоков, как бы вы порекомендовали решить мою проблему? любые примеры? –

ответ

0

В качестве примера

коснуться как

if (!PRlist.get(i).isAlive()){ 
    int exitCode=PRlist.get(i).exitValue(); 
    //Do something with exitValue 

    PRlist.get(i).destroy(); 
    PRlist.get(i).destroy(); 
    PRlist.remove(i); 
    try { 
     Process PR = new ProcessBuilder().inheritIO().command(commandsList.get(i)).redirectInput(Redirect.INHERIT).start(); 
     System.out.println(commandsList.get(i)[12] + " stream re-established at " + LocalDateTime.now().format(frmt)); 
     PRlist.add(i,PR); 
     } catch (IOException ex) {ex.printStackTrace();} 
     } 

Примеры с errorStream могут быть более сложными, но идея глядя на исключение, которое отправляется в errorStream посредством обработки текста.

+0

Спасибо, я попробую этот подход. –

+0

Эта идея отлично работает для меня. Спасибо. Все еще пытаюсь попробовать подход, представленный @BorisShchegolev, чтобы посмотреть, не спасет ли он меня память. –

+0

Добро пожаловать. Я думаю, что подход Threads дает вам больше контроля над вашими подпроцессами. Я не знаю о памяти, потому что открытие многих потоков может быть ресурсоемким в любом случае – Massimo

0

Может быть, вы можете работать с методами

**public ProcessBuilder.Redirect redirectError()** 
Returns this process builder's standard error destination. Subprocesses subsequently started by this object's start() method redirect their standard error to this destination. The initial value is Redirect.PIPE. 
Returns: 
this process builder's standard error destination 

Или

public abstract int exitValue() 
Returns the exit value for the subprocess. 
Returns: 
the exit value of the subprocess represented by this Process object. By convention, the value 0 indicates normal termination. 
Throws: 
IllegalThreadStateException - if the subprocess represented by this Process object has not yet terminated 
+0

Можете ли вы привести небольшой пример для своей идеи? –

+0

Пример для примера – Massimo

+0

Что это? Я думаю, что в вашем комментарии чего-то не хватает. –

0

ОК, с Java Threads вы могли бы сделать это следующим образом:

class MyThreadedApp { 

    // main() here 

    /** 
    * Starting a new thread 
    */ 
    private void start() { 
     new Thread(() -> { 
      try { 
       new Worker().run(); 
      } catch (Exception ex) { 
       threadEnded(ex); 
      } 
     }).start(); 
    } 

    /** 
    * Handle errors 
    * 
    * @param ex Error 
    */ 
    private void threadEnded(Exception ex) { 
     System.out.println(ex.getMessage()); 
    } 
} 

/** 
* My worker thread 
*/ 
class Worker { 

    void run() throws IOException { 
     // Do my stuff here 
    } 
} 

Это простой пример, чтобы продемонстрировать поток данных. На практике вы могли бы использовать некоторые технологии @lscoughlin.

+0

Спасибо. Я вижу, что вы пытаетесь поймать исключение, когда «Worker(). Run', чтобы использовать ошибку, чтобы что-то сделать. Будет ли такая же концепция работать, если нет ошибки?например, сервер ответил 404 и ошибка не была брошена, поток только прекратил работать. –

+0

Для любого другого условия, то «HTTP 20x» ваш рабочий поток должен выдать исключение. Это обычно довольно легко достичь. –

 Смежные вопросы

  • Нет связанных вопросов^_^