问题: 我需要每隔 10 秒以固定速率调用一个 dao 方法,然后我需要检查结果是否有效,如果是则退出,否则继续每 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 ??
}
}
}
用户只需提供task的实现和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 并获取结果。为了以下目的,我不得不使用三个执行器:
- 执行器以固定间隔运行任务
- 执行者在超时结束时停止一切
- 如果在超时之前获得有效结果,则执行程序将停止所有操作。
有人可以建议一个更好的方法吗,对于这样一个微不足道的任务来说这似乎很复杂?