当前位置: 首页 > 面试题库 >

预定执行程序:以固定速率轮询结果,如果超时或结果有效,则退出

訾朗
2023-03-14
问题内容

问题:
我有一个要求以固定速率调用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 ??
        }

    }
}

用户只需简单地提供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并获得结果。我出于以下目的不得不使用三个执行器:

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

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


问题答案:

使它成为自调度任务。用伪代码:

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

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



 类似资料:
  • 问题内容: 是否可以以预定顺序进行声明,即 选择ID 7,2,5,9和8 并以该顺序返回它们 ,仅基于ID字段? 这两个语句以相同顺序返回它们: 问题答案: 我不认为这是可能的,但是在这里找到了一个博客条目,似乎可以满足您的需求: 将给不同的结果 返回给定第二个参数的位置,因此对于上面的第一种情况,7的位置在集合中的位置1,2的位置在2,依此类推-mysql在内部得出类似 然后按的结果排序。

  • 我有一个包含1600万条记录的MySql表,由于一些迁移工作,我正在读取整个MySql表。 以下代码用于在MySql中流式传输大型结果集 但这是一次流式传输一个结果,这是否意味着我们每行都命中MySql服务器 在使用流时,我们可以设置如下语句:setFetchSize(1000); 我想减少到服务器的往返次数,同时流式传输大型 ResultSet

  • 模仿大众点评网的团购页面,整体布局滑动到顶端时,信息描述的view停止在顶端,其他布局仍可滑动。在demo中的表现是:白色视图往上滑动接近屏幕顶端时,将停止(表现为表层出现一个暗红色的视图)滑动,底部的视图继续往上移动。底部视图往下移动时,当滑动到一定位置时(表现为底部的白色视图和暗红色视图重合),白色视图将继续移动。 [Code4App.com]

  • 效果快速参考艺术效果 效果 动作 “效果 ”>“3D” 将开放路径或封闭路径,或是位图对象,转换为可以旋转、打光和投影的三维 (3D) 对象。另请参阅:第 219 页的 “创建 3D 对象 ” “效果 ”>“艺术效果 ” 在传统介质上模拟应用绘画效果。另请参阅:第 320 页的 “艺术效果 ” “效果 ”>“模糊 ” 可在图像中对指定线条和阴影区域的轮廓边线旁的像素进行平衡,从而润色图像,使过渡显

  • 要运行查询,在工具栏中点击 运行 。如果查询语句是正确的,该查询将被运行,如果该查询应该返回数据,结果 选项卡会打开查询返回的数据。如果运行查询时发生错误,运行停止,显示相应的错误信息。 结果 选项卡以网格显示查询返回的结果数据。数据可以用两种模式显示:网格查看 和 表单查看。详细信息请看表查看 器。 提示:Navicat 支持返回 10 个结果集。 注意:你可以通过选择 查看 -> 显示结果 -

  • 你可以在任何的服务器运行查询。在工具栏的下拉式列表中选择目标服务器和数据库。然后点击 “运行”。如果该查询语句是正确的,它将被运行。如果该查询应该返回数据,“结果”选项卡会打开并显示返回的数据。如果运行查询时发生错误,运行会停止并显示相应的错误信息。 “结果”选项卡以网格显示查询返回的结果数据。数据可以用三种模式显示:网格视图、树视图和 JSON 视图。详细信息请参阅数据查看器。 【注意】Navi