Как найти будущее в Spring ThreadPoolTaskScheduler - PullRequest
0 голосов
/ 17 октября 2018

Я использую Spring ThreadPoolTaskScheduler, и мне нужно найти и отменить будущее по некоторым условиям.

Правильно ли иметь поле ScheduledFuture в задаче Runnable и собирать задачи в ArrayList?Должен ли я использовать CopyOnWriteArrayList?

class Task implements Runnable {
  public Task(int id) {
    this.id = id;
  }
  private final int id;
  private ScheduledFuture future;
  public void setFuture(ScheduledFuture future) {
    this.future = future;
  }
  public ScheduledFuture getFuture() {
    return future;
  }
  public int getId() {
    return this.id;
  }
  public void run() {
    System.out.println(this.id);
  }
}

@Service
@RequiredArgsConstructor
public class ServiceTest {
  private final ThreadPoolTaskScheduler threadPoolTaskScheduler;
  private final ArrayList<Task> tasks = new ArrayList<Task>();
  @PostConstruct
  public void registerTasks() {
    for (int i = 0; i < 3; i++) {
      Task task = new Task(i);
      ScheduledFuture future = threadPoolTaskScheduler.schedule(task, new 
      PeriodicTrigger(100));
      task.setFuture(future);
      tasks.add(task);
    }
  }
  public void stopTask(int id) {
    Iterator<Task> it = tasks.iterator();
    while(it.hasNext()) {
      Task task = it.next();
      if (task.getId() == id) {
        task.getFuture().cancel(false);
        it.remove();
      }
    }
  }
}

1 Ответ

0 голосов
/ 17 октября 2018

Правильно ли иметь поле ScheduledFuture в задаче Runnable?

С чисто технической точки зрения, я не думаю, что существует какая-либо проблема в сохранении ScheduledFuture в случаеКласс Task, который реализует Runnable, потому что ваш экземпляр класса Task будет просто сохранять его как информацию о состоянии, которую вы можете использовать позже в своем коде, как вы это делали в методе stopTask () .Кроме того, просто отметим, что здесь вы используете PeriodicTrigger, что означает, что поток будет продолжать выполняться после предоставленного интервала времени 100 мс, если задача не будет отменена.

ПРИМЕЧАНИЕ. Убедитесь, что фактический метод run () никоим образом не изменяет будущее переменной класса.(хотя в этом вопросе это не сделано, ваш реальный код также не должен иметь таких изменений в будущей переменной внутри метода run ())

собирать задачи в ArrayList?Должен ли я использовать CopyOnWriteArrayList?

Использование ArrayList здесь не повредит, так как вы используете это из любого многопоточного контекста.Если этот список должен был использоваться в многопоточном контексте, то вы, вероятно, могли бы подумать об использовании CopyOnWriteArrayList.Чтобы быть точным, ваш класс ServiceTest имеет метод registerTasks (), который изменяет / обращается к вашему списку, и этот метод не вызывается многопоточным способом согласно коду, показанному в вопросе.Таким образом, здесь нет необходимости в CopyOnWriteArrayList.

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


ОБНОВЛЕНИЕ: О, хорошо, я пропустил эту модификацию через итератор.Я согласен, что метод stopTask () может быть доступен многопоточным способом, если он может быть вызван через контроллер REST.Однако CopyOnWriteArrayList не поддерживает метод remove () в своем итераторе () на тот случай, если вы думаете об этом.Кроме того, использование CopyOnWriteArrayList рекомендуется только в том случае, если у вас больше операций чтения, чем операций записи в списке.На самом деле он предназначен для безопасных обходов, где большинство операций чтения с использованием итератора.Я бы предложил синхронизировать метод stopTask () или использовать Collections.synchronizedList (tasks)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...