Dre*_*kes 17 clojure periodic-task
我正在寻找一种在Clojure中定期调用函数的简单方法.
JavaScript setInterval有我想要的那种API.如果我在Clojure中重新构想它,它看起来像这样:
(def job (set-interval my-callback 1000))
; some time later...
(clear-interval job)
Run Code Online (Sandbox Code Playgroud)
出于我的目的,我不介意这是创建一个新线程,在线程池或其他东西中运行.时机也是准确的并不重要.事实上,提供的时间段(以毫秒为单位)可能只是一个呼叫结束和下一个呼叫开始之间的延迟.
A. *_*ebb 28
如果你想要非常简单
(defn set-interval [callback ms]
(future (while true (do (Thread/sleep ms) (callback)))))
(def job (set-interval #(println "hello") 1000))
=>hello
hello
...
(future-cancel job)
=>true
Run Code Online (Sandbox Code Playgroud)
再见.
Nie*_*lsK 20
Clojure还有很多调度库:(从简单到非常先进)
直接来自at-at的github主页的例子:
(use 'overtone.at-at)
(def my-pool (mk-pool))
(let [schedule (every 1000 #(println "I am cool!") my-pool)]
(do stuff while schedule runs)
(stop schedule))
Run Code Online (Sandbox Code Playgroud)
使用(every 1000 #(println "I am cool!") my-pool :fixed-delay true),如果你想任务结束之间一秒钟的延迟和明年的开始,而不是两次启动之间.
最简单的方法是在一个单独的线程中有一个循环.
(defn periodically
[f interval]
(doto (Thread.
#(try
(while (not (.isInterrupted (Thread/currentThread)))
(Thread/sleep interval)
(f))
(catch InterruptedException _)))
(.start)))
Run Code Online (Sandbox Code Playgroud)
您可以使用Thread.interrupt()以下命令取消执
(def t (periodically #(println "Hello!") 1000))
;; prints "Hello!" every second
(.interrupt t)
Run Code Online (Sandbox Code Playgroud)
你甚至可以future用来包裹循环并future-cancel阻止它.
我对此进行了编码,其界面略微修改,而不是原始问题中指定的界面.这就是我想出来的.
(defn periodically [fn millis]
"Calls fn every millis. Returns a function that stops the loop."
(let [p (promise)]
(future
(while
(= (deref p millis "timeout") "timeout")
(fn)))
#(deliver p "cancel")))
Run Code Online (Sandbox Code Playgroud)
欢迎反馈.
小智 8
这就是我如何使用停止通道执行core.async版本.
(defn set-interval
[f time-in-ms]
(let [stop (chan)]
(go-loop []
(alt!
(timeout time-in-ms) (do (<! (thread (f)))
(recur))
stop :stop))
stop))
Run Code Online (Sandbox Code Playgroud)
和用法
(def job (set-interval #(println "Howdy") 2000))
; Howdy
; Howdy
(close! job)
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用java.util.Timer的schedualeAtFixedRate方法
编辑 - 在单个计时器上复用任务,并停止单个任务而不是整个计时器
(defn ->timer [] (java.util.Timer.))
(defn fixed-rate
([f per] (fixed-rate f (->timer) 0 per))
([f timer per] (fixed-rate f timer 0 per))
([f timer dlay per]
(let [tt (proxy [java.util.TimerTask] [] (run [] (f)))]
(.scheduleAtFixedRate timer tt dlay per)
#(.cancel tt))))
;; Example
(let [t (->timer)
job1 (fixed-rate #(println "A") t 1000)
job2 (fixed-rate #(println "B") t 2000)
job3 (fixed-rate #(println "C") t 3000)]
(Thread/sleep 10000)
(job3) ;; stop printing C
(Thread/sleep 10000)
(job2) ;; stop printing B
(Thread/sleep 10000)
(job1))
Run Code Online (Sandbox Code Playgroud)