問題: 修正レートで dao メソッドを 10 秒ごとに呼び出す必要があるため、結果が有効かどうかを確認する必要があります。タイムアウト (たとえば 2 分) が終了しました。
アプローチ: タスクとスケジューラ ロジックを分離しておき、同様の要件を持つさまざまなクラスで使用できるようにタスクを記述したいと考えています。
私が考えることができる 1 つの方法は、新しいポーラー タスクを定義することです。
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 の実装を提供する必要があります。
次に、プーリングの頻度とタイムアウトを取り、スケジュールされたエグゼキューターを作成してこのタスクを送信する別のクラスを定義できます
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 を返すまで待機して結果を取得できるようになりました。次の目的で 3 つのエグゼキューターを使用する必要がありました。
- 固定間隔でタスクを実行するエグゼキュータ
- タイムアウトが終了したときにすべてを停止するエグゼキュータ
- タイムアウト前に有効な結果が得られた場合、executor はすべて停止します。
誰かがより良いアプローチを提案できますか?