2014-10-12 2 views
1

У меня есть приложение Java, которое должно выполняться как процесс Linux. Он подключается к удаленной системе через соединение сокета. У меня есть два потока, которые проходят весь жизненный цикл программы. Это краткая версия моей точки входа в приложение:Шаблон проектирования ExecutorService

public class SMPTerminal { 
    private static java.util.concurrent.ExcecutorService executor; 

    public static void main(String[] args) { 
     executor = Executors.newFixedThreadPool(2); 
     Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownHook())); 
     run(new SMPConsumer()); 
     run(new SMPMaintainer()); 
    } 

    public static void run(Service callableService) { 
     try { 
      Future<Callable> future = executor.submit(callableService); 
      run(future.get().restart()); 
     } catch (InterruptedException | ExcecutionException e) { 
      // Program will shutdown 
     } 
    } 
} 

Это Service интерфейс:

public interface Service() { 
    public Service restart(); 
} 

И это одна реализация Service интерфейса:

public class SMPConsumer implements Callable<Service>, Service { 
    @Override 
    public Service call() throws Exception { 
     // ... 
     try { 
      while(true) { 
       // Perform the service 
      } 
     } catch (InterruptedException | IOException e) { 
      // ... 
     } 
     return this; // Returns this instance to run again 
    } 
    public Service restart() { 
     // Perform the initialization 
     return this; 
    } 
} 

я достиг этой структуры после того, как у меня возникают головные боли, когда временный сбой IO или другие проблемы вызывают остановку моего приложения. Теперь, если моя программа сталкивается с проблемой, она не завершается полностью, а просто инициализирует себя с нуля и продолжается. Но я думаю, что это немного натянуто, и я нарушаю правила проектирования ООП. Мои вопросы

  • Является ли эта ошибка обработки правильной или эффективной?
  • Какие проблемы я могу столкнуться в будущем?
  • Должен ли я изучать какой-либо специальный шаблон дизайна для моей проблемы?
+1

Возможно, вам понадобится использовать «BlockingQueue», который будет действовать как балансировщик нагрузки, вы можете просто перегрузить ваш «ExcecutorService» до такой степени, что он не сможет выполнить все запросы. – PeterK

+0

@PeterK служба «ExecutorService» работает только с потоками, и я запускаю каждый поток (реализация интерфейса «Service»), если поток прерывается из-за исключения IO и т. Д., Которое невозможно обработать из потока. Также я использую очередь сообщений внутри 'SMPConsumer'. –

ответ

0

Вы, возможно, не заметили, но ваш метод run ждет, пока callableService закончить выполнение до возвращения. Таким образом, вы не можете одновременно запускать две службы. Это потому, что Future.get() waits until the task computation completes.

public static void run(Service callableService) { 
    try { 
     Future<Callable> future = executor.submit(callableService); 
     run(future.get().restart()); // <=== will block until task completes! 
    } catch (InterruptedException | ExcecutionException e) { 
     // Program will shutdown 
    } 
} 

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

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

Так что я предполагаю, что блокировка в этом случае не предусмотрена. Возможно, ваш метод run должен выглядеть примерно так:

public static void run(Service callableService) { 
    executor.submit(() -> { 
     Service result = callableService.call(); 
     run(result.restart()); 
     return result; 
    }); 
} 

Этот фрагмент кода является просто основным, вы можете расширить его для обработки исключительных ситуаций.

+0

О да, это делает «ExecutorService» непригодным для использования! –

0
  • Является ли этот вид обработки отказов правильно или эффективно? Это зависит от контекста приложения и того, как вы используете обработку ошибок.

  • Может возникнуть ситуация, когда сбои ввода/вывода и т. Д. Не обрабатываются должным образом.

  • Похоже, вы уже используете шаблон дизайна адаптера. Посмотрите на адаптер шаблона проектирования http://www.oodesign.com/adapter-pattern.html

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