预定执行程序:以固定速率轮询结果,如果超时或结果有效,则退出 [英] Scheduled executor: poll for result at fix rate and exit if timeout or result valid

查看:64
本文介绍了预定执行程序:以固定速率轮询结果,如果超时或结果有效,则退出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题: 我有一个要求以固定速率调用dao方法,例如每10秒调用一次,然后我需要检查结果是否有效(如果存在),否则请每隔10秒继续调用该方法,直到获得有效结果或定义的超时为止(例如2分钟)结束.

Problem: I have a requirement to call a dao method at fix rate say every 10 sec, then I need to check if the result is valid if yes exit, else keep on calling that method every 10 sec till I get a valid result or defined time out (say 2 min) is over.

方法: 我想将任务和调度程序逻辑分开,并编写一种任务,使其可以被具有相似需求的不同类使用.

Approaches: I want to keep the task and scheduler logic separate, and write a task in such a way that it can be used by different classes having similar requirement.

我能想到的一种方法是定义一个新的轮询器任务

One way I can think is to define a new poller task

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的实现;

User need to simply provide implementation of task and isValid;

然后,我们可以定义一个单独的类,该类需要合并频率和超时并创建计划的执行程序并提交此任务

Then we can define a separate class that takes pooling freq and timeout and creates a scheduled executor and submit this task

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并获取结果. 我必须出于以下目的使用三个执行器:

now user can wait till pollerExecutor.isDone returns true and get the result. I had to use three executors for following purposes:

  1. 执行器以固定间隔运行任务
  2. 执行器在超时结束时停止所有操作
  3. 如果超时之前获得有效结果,执行器将全部停止.

有人可以建议一种更好的方法吗,这对于如此琐碎的任务来说似乎很复杂?

Can someone please suggest a better approach, this seems to be complicated for such a trivial task ?

推荐答案

使其成为自调度任务.用伪代码:

Make it a self-scheduling task. In pseudo code:

public class PollingTaskRunner {

...
CountDownLatch doneWait = new CountDownLatch(1);
volatile boolean done;

PollingTaskRunner(Runnable pollingTask, int frequency, int period) {
    ...
    endTime = now + period;
    executor.schedule(this, 0);
}

run() {

    try {
        pollingTask.run();
    } catch (Exception e) {
        ...
    }
    if (pollingTask.isComplete() || now + frequency > endTime) {
        done = true;
        doneWait.countDown();
        executor.shutdown();
    } else {
        executor.schedule(this, frequency);
    }
}

await() {
    doneWait.await();
}

isDone() {
    return done;
}
}

它并不那么复杂,但是在您第一次运行/测试时添加大量调试语句,这样您就知道发生了什么.一旦按预期运行,就很容易重用该模式.

It is not that complicated but add plenty of debug statements the first time you run/test this so you know what is going on. Once it is running as intended, it is easy to re-use the pattern.

这篇关于预定执行程序:以固定速率轮询结果,如果超时或结果有效,则退出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆