复杂的时间调度器

Posted h5it

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了复杂的时间调度器相关的知识,希望对你有一定的参考价值。

需求:设计一个自由可灵活配置的时间调度器,有a,b,c,d...很多个需要被调度的方法(方法名称的命名可随意),调度有两种形式,一个是顺序调用(例如调度完a后才能调度b),一个是间隔某个时间进行循环调度。用一个统一的方法进行封装可以实现下列的例子:

1,可以为5秒后调用a,3秒后调用b,10秒后调用。c...z方法不执行(不执行的方法可以设计成不传递参数),那么在第14秒的时候开始重新从0秒循环,又变成第一秒后调用a,3秒后调用b,这样循环往复;

2,每间隔6秒调用一次a,每间隔4秒调用一次b,c...z方法不执行;

3,第一秒先执行a,3秒后执行b,但是c却是每间隔3秒执行一次,d是每间隔4秒执行一次,a和b是每4秒进行一次循环;

4,a不执行,b和c每间隔3秒执行一次,d不执行;

 

/**
     *  loop
     *  delay
     *  同步队列
     *  同步延迟队列
     *  异步延迟队列 
     */
    class Schedule {
      constructor() {
        this.asynchroQueueList = [];
        this.asynchroDelayQueueList = [];
        this.asyncDelayQueueList = [];
        this.timer = null;
      }
      // 同步队列,a -> b -> c -> d
      addAsynchro(fn, option) {
        this.asynchroQueueList.push({fn: fn, ...option});
        return this;
      }
      // 同步不延迟队列 a -> b -> c -> d
      addAsynchroDelay(fn, option) {
        this.asynchroDelayQueueList.push({fn: fn, ...option});
        return this;
      }
      // 异步队列 a = b = c
      addAsyncDelay(fn, option) {
        this.asyncDelayQueueList.push({fn: fn, ...option})
        return this;
      }
      runAsynchro() {
        const len = this.asynchroQueueList.length;
        if (len === 0) {
          return;
        }
        let index = 0;
        while(index < len) {
          const fn =this.asynchroQueueList[index].fn;
          fn();
          index ++;
        }
      }
      stop(fn, delay) {
        return new Promise((resolve) => {
          this.timer = setTimeout(() => {
            fn();
            resolve();
          }, delay)
        })
      }
      runAsynchroDelay() {
        const len = this.asynchroDelayQueueList.length;
        if (len === 0) {
          return;
        }
        let index = 0;
        const doloop = (i) => {
          //  console.log(asynchroDelayQueueList)
          const fn = this.asynchroDelayQueueList[i].fn;

          // console.time(‘test‘+i)
          let delay = 0;
          let current = this.asynchroDelayQueueList[i];
          if (current.offset && current.offset  > 0) {
            delay = current.offset;
            current.offset = 0;
          } else {
            delay = current.delay;
          }
            this.stop(fn, delay)
            .then(() => {
              // console.timeEnd(‘test‘ + i)
            index ++;
            if (index < len) {
              doloop(index);
            } else {
              index = 0;
              doloop(index);
            }
            })
        }
        doloop(0);
      }
      runAsyncDelay() {
        const len = this.asyncDelayQueueList.length;
        if (len === 0) {
          return;
        }
        let index = 0;
        
        const loop = (fn, delay) => {
          // console.time(‘test1‘ + i + 100)
          this.timer = setTimeout(() => {
            fn();
            loop(fn, delay);
          }, delay);
        }

        // console.log(this.asyncDelayQueueList[0])
        for (let i = 0; i < len; i ++) {
          loop(this.asyncDelayQueueList[i].fn, this.asyncDelayQueueList[i].delay);
        }
       
      }
      run() {
        this.runAsyncDelay();
        this.runAsynchro();
        this.runAsynchroDelay();
      }
    }

    function a() {
      console.log(‘aaaaaaaaaaaaaaaaaaaaaaaaaa‘);
    }
    function b() {
      console.log(‘bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb‘);
    }
    function c() {
      console.log(‘cccccccccccccccccccccccccccccccccc‘);
    }
    function d() {
      console.log(‘ddddddddddddddddddddddddddddddd‘);
    }

    // 1,可以为5秒后调用a,3秒后调用b,10秒后调用。c...z方法不执行(不执行的方法可以设计成不传递参数),那么在第14秒的时候开始重新从0秒循环,又变成第一秒后调用a,3秒后调用b,这样循环往复;
    // const schedule = new Schedule();
    // schedule.addAsynchroDelay(a, { delay: 3000, offset: 5000}).addAsynchroDelay(b, { delay: 3000}).addAsynchroDelay(c, { delay: 14000})
    // schedule.run();
    // 3,第一秒先执行a,3秒后执行b,但是c却是每间隔3秒执行一次,d是每间隔4秒执行一次,a和b是每4秒进行一次循环;
    const schedule1 = new Schedule();
    schedule1.addAsynchroDelay(a, { delay: 1000 })
    .addAsynchroDelay(b, { delay: 3000 })
    .addAsyncDelay(c, { delay: 3000 })
    .addAsyncDelay(d, { delay: 4000})
    schedule1.run();
    // 2,每间隔6秒调用一次a,每间隔4秒调用一次b,c...z方法不执行;
    // const schedule2 = new Schedule();
    // schedule2.addAsyncDelay(a, { delay: 4000 }).addAsyncDelay(b, { delay: 4000 })
    // schedule2.run()
    // 4,a不执行,b和c每间隔3秒执行一次,d不执行;
    // const schedule3 = new Schedule();
    // schedule3.addAsyncDelay(b, { delay: 3000 }).addAsyncDelay(c, { delay: 3000 })
    // schedule3.run();

 

以上是关于复杂的时间调度器的主要内容,如果未能解决你的问题,请参考以下文章

工作流调度器azkaban的安装和使用

关于代码片段的时间复杂度

以下代码片段的时间复杂度是多少?

Azkaban 工作流调度器

使用片段着色器在特定位置绘制完美的水平线

工作流调度器azkaban(以及各种工作流调度器比对)