Лучшие практики Исполнителя Java для Задач, которые Должны Работать Навсегда

Я работаю над проектом Java, где у меня должно быть несколько задач, работающих асинхронно. Я ведусь полагать, что Исполнитель является лучшим способом для меня сделать это, таким образом, я ознакомляюсь с ним. (Yay, заплаченный для изучения!) Однако мне не ясно, что лучший способ состоит в том, чтобы выполнить то, что я пытаюсь сделать.

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

  • Если любая задача выдаст исключение, то обертка поймает ее и перезапустит задачу.
  • Если любая задача будет работать к завершению, то обертка заметит и перезапустит задачу.

Теперь, нужно отметить, что реализация для обеих задач перенесет код в run() в бесконечном цикле, который никогда не будет работать к завершению с блоком попытки/выгоды, который должен обработать все исключения на этапе выполнения, не разрушая цикл. Я пытаюсь добавить другой слой уверенности; если или я или кто-то, кто следует за мной, делаем что-то глупое, которое побеждает эти гарантии и останавливает задачу, приложение должно реагировать соответственно.

Существует ли лучшая практика для приближения к этой проблеме, которую рекомендовали бы люди, более опытные, чем я?

FWIW, я хлестал этот тестовый класс:


public class ExecTest {

   private static ExecutorService executor = null;
   private static Future results1 = null;
   private static Future results2 = null;

   public static void main(String[] args) {
      executor = Executors.newFixedThreadPool(2);
      while(true) {
         try {
            checkTasks();
            Thread.sleep(1000);
         }
         catch (Exception e) {
            System.err.println("Caught exception: " + e.getMessage());
         }
      }
   }

   private static void checkTasks() throws Exception{
      if (results1 == null || results1.isDone() || results1.isCancelled()) {
         results1 = executor.submit(new Test1());
      }

      if (results2 == null || results2.isDone() || results2.isCancelled()) {
         results2 = executor.submit(new Test2());
      }
   }
}

class Test1 implements Runnable {
   public void run() {
      while(true) {
         System.out.println("I'm test class 1");
         try {Thread.sleep(1000);} catch (Exception e) {}
      }

   }
}

class Test2 implements Runnable {
   public void run() {
      while(true) {
         System.out.println("I'm test class 2");
         try {Thread.sleep(1000);} catch (Exception e) {}
      }
   }
}

Это ведет себя способ, которым я хочу, но я не знаю, существуют ли какие-либо глюки, неэффективность или совершенно заблуждающееся ожидание для удивления меня. (На самом деле, учитывая, что я плохо знаком с этим, я был бы потрясен, если бы не было чего-то неправильного/нецелесообразного относительно этого.)

Любое понимание одобрено.

36
задан Raedwald 25 April 2014 в 13:06
поделиться

3 ответа

Я столкнулся с подобной ситуацией в моем предыдущем проекте, и после того, как мой код взорвался перед лицом злой клиента, моих приятелей, и я добавил два больших безопасных охранника:

  1. в бесконечной петле, поймать ошибки тоже не только исключения. Иногда произошедшие вещи, и Java бросает на вас ошибку, а не исключение.
  2. Используйте выключатель заднего выключения, поэтому, если что-то пойдет не так, и не восстанавливается, вы не обогатите ситуацию, с нетерпением зачитывая еще одну петлю. Вместо этого вам нужно подождать, пока ситуация не вернется к нормальной, а затем начать снова.

Например, у нас была ситуация, когда база данных снизилась, и во время петли было брошено SQLException. К сожалению, результатом было то, что код снова прошел через петлю, только чтобы снова ударить одно и то же исключение и так далее. Журналы показали, что мы ударим то же SQLException примерно в 300 раз в секунду! ... Это произошло периодически несколько раз с незащищенным JVM-паузами в 5 секундах или около того, во время которого приложение не было отзывчивым, пока в конце концов ошибка была брошена, а поток умерла!

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

class Test1 implements Runnable {
  public void run() {
    boolean backoff = false;
    while(true) {
      if (backoff) {
        Thread.sleep (TIME_FOR_LONGER_BREAK);
        backoff = false;
      }
      System.out.println("I'm test class 1");
      try {
        // do important stuff here, use database and other critical resources
      }
      catch (SqlException se) {
       // code to delay the next loop
       backoff = true;
      }
      catch (Exception e) {
      }
      catch (Throwable t) {
      }
    }
  }
}

Если вы реализуете свои задачи таким образом, то я не вижу точки, имея третью нить «Watch-Dog» с методом CheckTasks (). Кроме того, по тем же причинам я изложил выше, я был бы осторожен, чтобы просто начать задачу снова с исполнителем. Сначала вы должны понять, почему задача не удалась, и является ли среда стабильного состояния, которое снова выполняет задачу, будет полезна.

31
ответ дан 27 November 2019 в 06:13
поделиться

Мне нужно увидеть весь файл, но я предполагаю, что вы либо не включаете исходный файл jQuery.js, либо у вас есть несколько элементов с идентификатором foo

-121--1296156-

Я предполагаю, что вы используете .Net WinForms.

Установите для свойства формы SunIcon значение false .

-121--2200533-

пробовали кварцевую рамку ?

0
ответ дан 27 November 2019 в 06:13
поделиться

Кроме того, чтобы взглянуть на это, я обычно запускаю Java-код против таких инструментов статического анализа, как PMD и FindBugs для поиска более глубоких проблем.

Специально для этого кода FindBugs не понравилось, что результаты1 и результаты2 не являются изменчивыми в ленивом init, и что методы run() могут игнорировать Исключение, так как они не обрабатываются явным образом.

В общем, я немного осторожен с использованием Thread.sleep для параллельного тестирования, предпочитая таймеры или завершающие состояния/условия. Callable может быть полезным в возвращении что-то в случае сбоя, который бросает исключение, если не в состоянии вычислить результат.

Для ознакомления с некоторыми лучшими практиками и получения дополнительной пищи для размышлений обратитесь к Конкурентоспособность на практике .

7
ответ дан 27 November 2019 в 06:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: