Geplanter Executor: Ergebnis mit fester Rate abfragen und beenden, wenn Timeout oder Ergebnis gültig sind

Problem: Ich muss eine Dao-Methode mit einer festen Rate aufrufen, etwa alle 10 Sekunden. Dann muss ich überprüfen, ob das Ergebnis gültig ist, wenn yes exit. Andernfalls muss ich diese Methode alle 10 Sekunden aufrufen, bis ich ein gültiges Ergebnis oder eine definierte Zeitüberschreitung erhalte (sprich 2 min) ist vorbei.

Ansätze: Ich möchte die Task- und Scheduler-Logik getrennt halten und eine Task so schreiben, dass sie von verschiedenen Klassen mit ähnlichen Anforderungen verwendet werden kann.

Eine Möglichkeit, die ich mir vorstellen kann, besteht darin, eine neue Poller-Aufgabe zu definieren

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 ??
        }

    }
}

Der Benutzer muss lediglich die Implementierung von task und isValid bereitstellen.

Anschließend können wir eine separate Klasse definieren, die Pooling-Frequenz und Timeout verwendet, einen geplanten Executor erstellt und diese Aufgabe übergibt

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;

    }

Jetzt kann der Benutzer warten, bis pollerExecutor.isDone true zurückgibt und das Ergebnis abruft. Ich musste drei Testamentsvollstrecker für folgende Zwecke einsetzen:

Executor, um die Task in festgelegten Intervallen auszuführenExecutor alle zu stoppen, wenn die Zeit abgelaufen istExecutor stoppt alle, wenn vor Ablauf der Zeit ein gültiges Ergebnis vorliegt.

Kann mir bitte jemand einen besseren Ansatz vorschlagen, dies scheint für eine so triviale Aufgabe kompliziert zu sein?

Antworten auf die Frage(2)

Ihre Antwort auf die Frage