Java高效的调度结构?

obf*_*ion 8 java algorithm scheduling

我为这个问题的长度道歉,但我认为重要的是要包含足够的细节,因为我正在寻找一个合适的方法解决我的问题,而不是一个简单的代码建议!


一般说明:

我正在开发一个项目,该项目要求能够以某个相对重复的间隔"安排"任务.

这些间隔是根据某个内部时间来表示的,它表示为一个整数,该整数在程序执行时递增(因此不等于实时).每次发生这种情况时,计划将被插入以检查由于在此时间步执行而导致的任何任务.

如果执行任务,则应该将其重新安排为在相对于当前时间的位置处再次运行(例如,以5个时间步长).此相对位置仅存储为Task对象的整数属性.

问题:

我正在努力决定如何构建这一点 - 部分是因为它是一组稍微难以寻找的搜索术语.

就目前而言,我在想每次计时器递增时我需要:

  1. 执行计划中"0"位置的任务
  2. 在相对位置再次将这些任务重新添加到计划中(例如,重复每5个步骤的任务将返回到位置5)
  3. 计划中的每组任务将使其"直到执行的时间"减少一个(例如,位置1处的任务将移动到位置0)

假设:

有几个假设可能限制我可以使用的可能解决方案:

  • 间隔必须是相对的,而不是特定的时间,并且被定义为距当前时间的整数步数
  • 这些间隔可以取任何整数值,例如不受限制.
  • 可以为相同的时间步长安排多个任务,但是它们的执行顺序并不重要
  • 所有执行都应保留在单个线程中 - 由于其他约束,多线程解决方案适用

我的主要问题是:

我如何设计此计划以有效的方式工作?什么数据类型/集合可能有用?

我应该考虑另一种结构/方法吗?

我是否错误地拒绝调度框架(例如Quartz),它似乎在"真实"时域而非"非真实"时域中工作更多?


非常感谢任何可能的帮助.如有需要,请随时评论以获取更多信息,我将在任何需要的地方进行编辑!

flo*_*lob 1

怎么样,它使用您自己的 Ticks 和executeNextInterval():

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class Scheduler {
    private LinkedList<Interval> intervals = new LinkedList<Scheduler.Interval>();

    public void addTask(Runnable task, int position) {
        if(position<0){
            throw new IllegalArgumentException();
        }
        while(intervals.size() <= position){
            intervals.add(new Interval());
        }
        Interval interval = intervals.get(position);
        interval.add(task);
    }

    public void executeNextInterval(){
        Interval current = intervals.removeFirst();
        current.run();
    }
    private static class Interval {
        private List<Runnable> tasks = new ArrayList<Runnable>();
        public void add(Runnable task) {
            tasks.add(task);
        }
        public void run() {
            for (Runnable task : tasks) {
                task.run();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您可能想要添加一些错误处理,但它应该可以完成您的工作。

这里有一些单元测试:)

import junit.framework.Assert;

import org.junit.Test;

public class TestScheduler {
    private static class Task implements Runnable {
        public boolean didRun = false;
        public void run() {
            didRun = true;
        }       
    }
    Runnable fail = new Runnable() {
        @Override
        public void run() {
            Assert.fail();
        }
    };

    @Test
    public void queue() {
        Scheduler scheduler = new Scheduler();
        Task task = new Task();
        scheduler.addTask(task, 0);
        scheduler.addTask(fail, 1);
        Assert.assertFalse(task.didRun);
        scheduler.executeNextInterval();
        Assert.assertTrue(task.didRun);
    }
    @Test
    public void queueWithGaps() {
        Scheduler scheduler = new Scheduler();
        scheduler.addTask(fail, 1);
        scheduler.executeNextInterval();
    }
    @Test
    public void queueLonger() {
        Scheduler scheduler = new Scheduler();
        Task task0 = new Task();
        scheduler.addTask(task0, 1);
        Task task1 = new Task();
        scheduler.addTask(task1, 1);
        scheduler.addTask(fail, 2);
        scheduler.executeNextInterval();
        scheduler.executeNextInterval();
        Assert.assertTrue(task0.didRun);
        Assert.assertTrue(task1.didRun);
    }
}
Run Code Online (Sandbox Code Playgroud)