Запланированный исполнитель: опросить результат по фиксированной ставке и выйти, если тайм-аут или результат верны
Проблема: У меня есть требование вызывать метод dao с фиксированной скоростью, скажем, каждые 10 секунд, а затем мне нужно проверить, верен ли результат, если да, выйдите, иначе продолжайте вызывать этот метод каждые 10 секунд, пока я не получу действительный результат или определенное время ожидания. (скажем, 2 минуты) закончилась.
подходы: Я хочу разделить логику задачи и планировщика и написать задачу таким образом, чтобы она могла использоваться разными классами, имеющими схожие требования.
Один способ, которым я могу думать, - это определить новую задачу опроса
public abstract class PollerTask<T> implements Runnable {
abstract public boolean isValid(T result);
abstract public T task();
private T result;
private volatile boolean complete;
public boolean isComplete() {
return complete;
}
public T getResult() {
return result;
}
@Override
final public void run() {
result = task();
if (complete = isValid(result)) {
//may be stop scheduler ??
}
}
}
Пользователю нужно просто обеспечить выполнение задачи и isValid;
Затем мы можем определить отдельный класс, который использует пул freq и timeout, создает запланированного исполнителя и отправляет эту задачу.
public class PollerTaskExecutor {
private int pollingFreq;
private int timeout;
private ScheduledExecutorService executor;
private ScheduledExecutorService terminator;
private ExecutorService condition;
private volatile boolean done;
private ScheduledFuture future;
public PollerTaskExecutor(int pollingFreq, int timeout) {
this.pollingFreq = pollingFreq;
this.timeout = timeout;
executor = Executors.newSingleThreadScheduledExecutor();
terminator = Executors.newSingleThreadScheduledExecutor();
condition = Executors.newSingleThreadExecutor();
}
public void submitTaskForPolling(final PollerTask pollerTask) {
future = executor.scheduleAtFixedRate(pollerTask, 0, pollingFreq, TimeUnit.SECONDS);
terminator.schedule(new Runnable() {
@Override
public void run() {
complete();
}
}, timeout, TimeUnit.SECONDS);
condition.execute(new Runnable() {
@Override
public void run() {
if (pollerTask.isComplete()) {
complete();
}
}
});
}
public boolean isDone() {
return done;
}
public void complete() {
future.cancel(false);
executor.shutdown();
terminator.shutdown();
condition.shutdown();
done = true;
}
Теперь пользователь может подождать, пока pollerExecutor.isDone вернет true и получить результат. Мне пришлось использовать трех исполнителей для следующих целей:
исполнитель для запуска задачи с фиксированным интерваломисполнитель, чтобы остановить все, когда время истеклоисполнитель, чтобы остановить все, если действительный результат получен до истечения времени ожидания.Может кто-нибудь предложить лучший подход, это кажется сложным для такой тривиальной задачи?