实施每秒重复不超过一次的定期作业

时间:2015-03-19 07:36:31

标签: java scala rx-java rx-scala

假设我们有类似的东西:

while (true) {
  val job = Future { doSomething(); 1 }
  val timeout = Future { Thread.sleep(1000); 2 }

  val both = for (j <- job; t <- timeout) {
    println("Done")
  }
  Await.result(both)
}

使用rx-java / scala?

的惯用解决方案是什么?

更新:如果代码中没有明显的话,可以稍微澄清一下。

ts n te n 开始和<的时间戳分别是doSomething()个职位的强>结束。

然后下一个作业应安排在 ts n + 1 = max(te n ,ts n + 1秒)

2 个答案:

答案 0 :(得分:2)

在完成RxScala和Observables提供的所有可能性之后,我必须说这里可能存在一个根本问题:可观察的用户不应该控制新值的发射。可观察量是事件的来源,订户是被动消费者。否则,例如,一个订户可能会影响observable发送给其他订户的输出。

如果您仍想使用observables,这是我提出的最佳解决方案。它zip可观察到ready和计时器,以便在计时器和作业完成时发出新事件。

def run(job: () => Unit) {

  val ready = Observable.create{ observer =>
    for(
      j <- future {job(); 1};
    ) observer.onNext(); 
  }

  Observable.timer(1 seconds).zip(ready).subscribe{ value =>
    run();
  }

}

run(doSomenthing); 

答案 1 :(得分:0)

如果我正确理解了问题,你需要进行递归调度(因为它似乎不会从作业中发出任何值)。以下是如何使用RxJava&#39; s Scheduler.Worker

执行此操作的示例
public class RecurringJob {
    static Subscription runJob(Runnable run) {
        Scheduler.Worker w = Schedulers.newThread().createWorker();
        MultipleAssignmentSubscription mas = new MultipleAssignmentSubscription();
        Action0 action = new Action0() {
            @Override
            public void call() {
                try {
                    run.run();
                    mas.set(w.schedule(this, 1, TimeUnit.SECONDS));
                } catch (Throwable t) {
                    t.printStackTrace();
                    w.unsubscribe();
                }
            }
        };
        mas.set(w.schedule(action, 1, TimeUnit.SECONDS));
        return mas;
    }
    public static void main(String[] args) throws InterruptedException {
        Subscription s = runJob(() -> System.out.println("Job"));
        Thread.sleep(10000);
        s.unsubscribe();
        System.out.println("Job stopped");
        Thread.sleep(3000);
        System.out.println("Done.");
    }
}