не может остановить Runnable, передающий себя в ScheduledExecutorService.schedule - PullRequest
0 голосов
/ 19 января 2012

У меня есть поллер из Runnable.Поллер передает себя в ScheduledExecutorService.Так как мне нужно различное время задержки в зависимости от задач, я использую «schedule» вместо «scheduleWithFixedDelay», что вызвало проблему ...

К сожалению, этот опросщик не может правильно отключиться ...

Журнал показывает, что: в начале «главный» поток планирует опросник;после этого поток 'poller18' (или любой другой идентификатор потока) планирует следующие опрашивающие устройства:

При уничтожении основной поток вызывает уничтожение, устанавливает для флага значение true и затем вызывает poller.shutdown;но поток 'poller18' никогда не видит этот флаг (он всегда равен false в schedulePoller), поэтому он будет продолжать планировать следующие опросы.

Мои вопросы: 1. isShuttingDown - это закрытое поле в классе.Я думал, что это будет разделено потоками, так как это не ThreadLocal.Почему не так?2. в этой ситуации есть ли другой способ, которым poller18 может быть уведомлен о завершении работы poller?

class Poller implements Runnable {
    private boolean isShuttingDown = false;
    private ScheduledExecutorService poller = null;

    @PostConstruct
    protected synchronized void start() {
      if (enabled && poller == null) {
          poller = Executors.newScheduledThreadPool(1);
          schedulePoller(1);
      }
   }

   protected synchronized void schedulePoller(final long period) {
      if (poller() == null || poller().isShutdown() || this.isShuttingDown) {
          return;
      }
      LOGGER.info("schedule a new poller");
      poller().schedule(this,
              period,
              TimeUnit.MILLISECONDS);
   }

   public void run() {
      ... do work ...
      if (more work)
           schedulePoller(1);
      else
           schedulePoller(10);
   }

   public void destroy() {
      this.isShuttingDown = true;
      poller.shutdown();
      while (!poller.awaitTermination(SHUTDOWN_WAIT_SECONDS, TimeUnit.SECONDS)) {
          LOGGER.info("Waiting for remaining tasks to finish.");
          poller.shutdown();
      }
      LOGGER.info("All remaining tasks have finished.");
   }
}

А в весеннем конфиге я устанавливаю destroy_method для destroy ().

МногиеСпасибо!Пожалуйста, дайте мне знать, если какие-либо путаницы в моем описании.

Ответы [ 3 ]

0 голосов
/ 19 января 2012

Javadoc не очень ясен относительно поведения новых расписаний, если исполнитель закрывается. В моем понимании, он должен отклонить новые графики.

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

0 голосов
/ 22 января 2012

При доступе к общему состоянию (isShuttingDown), независимо от того, есть ли у него права на чтение или запись, необходимо всегда сохранять одну и ту же блокировку, чтобы иметь согласованное общее состояние между потоками.Метод destroy () не синхронизирован и, следовательно, не удерживает одну и ту же блокировку объекта (неявную блокировку для текущего экземпляра класса / this), в то время как он изменяет переменную общего состояния.Скорее всего, именно поэтому isShuttingDown неправильно виден всем потокам ...

0 голосов
/ 19 января 2012

попробуй

private volatile boolean isShuttingDown = false;

Пул потоков

...