在clojure中实现cron类型的调度程序

时间:2012-06-27 20:43:52

标签: clojure

我正在寻找能够在特定时间触发事件的任何方法,

例如:我希望特定流程在上午9:30开始,然后我可以触发另一个流程,半小时后开始运行等。

提前致谢!


更新2:

感谢@ arthur-ulfeoldt和@ unknown-person,他在删除答案之前也建议使用https://github.com/samaaron/at-at。文档有点过时,但这是我的方式。

(use 'overtone.at-at)

(def my-pool (mk-pool))
;=> make a thread pool

(every 1000 #(println "I am super cool!") my-pool :initial-delay 2000) 
;=> starts print function every 1 sec after a 2 sec delay

(stop *1) 
;=> stops it

所以为了让它从9开始,间隔半小时,我会这样做:

(require '[clj-time.core :as t])
(require '[clj-time.coerce :as c])
(use 'overtone.at-at)

;Make Thread Pool
(def my-pool (mk-pool))

(def current-time (t/now))

(def current-date (t/date-time 
                    (t/year current-time)
                    (t/month current-time)
                    (t/day current-time)))

(def next-9-oclock
  (if (> 9 (t/hour current-time))
    (t/plus current-date (t/hours 9))
    (t/plus current-date (t/days 1) (t/hours 9))))

(def initial-delay
   (- (c/to-long next-9-oclock) (c/to-long current-time))

(every 1800000 
       #(println "I am super cool!") 
       my-pool 
       :initial-delay 
       initial-delay) 

更新

@ arthur-ulfeoldt,我不知道如何将一些java代码翻译成clojure。 http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ScheduledExecutorService.html

像:

final ScheduledFuture<?> beeperHandle = 
        scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);

final Runnable beeper = new Runnable() {
        public void run() { System.out.println("beep"); }
     };

整个示例

 class BeeperControl {
    private final ScheduledExecutorService scheduler = 
       Executors.newScheduledThreadPool(1);

    public void beepForAnHour() {
        final Runnable beeper = new Runnable() {
                public void run() { System.out.println("beep"); }
            };
        final ScheduledFuture beeperHandle = 
            scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
        scheduler.schedule(new Runnable() {
                public void run() { beeperHandle.cancel(true); }
            }, 60 * 60, SECONDS);
    }
 }

3 个答案:

答案 0 :(得分:10)

我需要的东西

  • 以全秒间隔开始计划任务,而不是具有高系统时间精度的整个分钟间隔。
  • 会根据需要生成尽可能多的线程,因此在较早的时间间隔内启动的任务可能会在以后的时间间隔内启动的任务中存在。

在为at-at,Monotony和Quartzite做了一些源代码阅读之后,我觉得它们不符合我所追求的要求(这真的是更为光明的东西)所以我写了自己的 - {{ 3}}

用法示例。

(require '[cronj.core :as cj])

(cj/schedule-task! {:id 0   :desc 0 
              :handler #(println "job 0:" %) 
              :tab "/5 * * * * * *"}) ;; every 5 seconds
(cj/schedule-task! {:id 1   :desc 1 
              :handler #(println "job 1:" %) 
              :tab "/3 * * * * * *"}) ;; every 3 seconds

(cj/start!) 

;; wait for scheduler to do its thing ......

(cj/stop!)

答案 1 :(得分:3)

java&gt; = 5.0有ScheduledExecutorService,涵盖了所有这些以及更多内容。 有一个名为at-at的clojure项目很好地包装了它(并且是它的一部分) 我个人最喜欢的项目之一Overtone)

您可能会发现其他有用的问题Executing code at regularly timed intervals in Clojure

来自引言:

 The schedule methods create tasks with various delays and return a task object that can be     
 used to cancel or check execution. The scheduleAtFixedRate and scheduleWithFixedDelay   
 methods create and execute tasks that run periodically until cancelled.

获得正确的cron或类型服务比听起来更难,所以使用现有的实现可能比滚动自己的实现有一些优势。

答案 2 :(得分:3)

我发现了一些用于调度的Clojure库,按复杂程度的升序排列:

  • Overtone/at-at,一个简单的提前调度程序
  • Monotony,一种调度程序,以人类直觉的方式安排事情。
  • Quartzite,一个基于Java Quartz Scheduler构建的强大的Clojure调度库。