在Clojure中,让代码定时运行的最佳方式是什么?我目前使用的是java.util.concurrent.ScheduledExecutorService,但那是Java - 是否有一种Clojure的方式来安排代码以延迟、可取消的方式运行?我看到的所有Clojure代码示例都使用Thread/sleep,这似乎也太Java了。
非常值得查看Overtone的源代码,特别是用于在特定时间安排事件的代码。
它是一个音乐合成系统,所以你必须希望他们有正确的定时代码!
此外,他们已将定时代码分离到单独的项目中(overtone/at-at),以便您可以轻松导入。它为底层Java库(即ScheduledThreadPoolExecutor和其它)提供了一个良好的Clojure包装器。语法如下:
;; run some-function every 500ms
(every 500 some-function)
您还可以在特定时间安排事件:
;; run some-other-function 10 seconds from now
(at (+ 10000 (now)) some-other-function)
从Clojure网站http://clojure.org/concurrent_programming获取以下信息:
在所有情况下,Clojure不会替换Java线程系统,而是与其一起工作。Clojure函数是java.util.concurrent.Callable,因此它们可以与Executor框架等一起使用。
听起来你已经以正确的方式进行了操作。
(import 'java.util.concurrent.Executors)
(import 'java.util.concurrent.TimeUnit)
(.scheduleAtFixedRate (Executors/newScheduledThreadPool 1)
#(println "Hello") 0 5 TimeUnit/SECONDS)
ScheduledExecutorService
只有 3(4)个方法,其中只有一个方法重载以接受 Callable
而不是 Runnable
,这会导致您计划的函数中的异常被静默地吞噬(甚至没有将任何内容打印到 stderr!)... 显然,我并不真正关心重复计划函数的结果,所以我并不需要整个 Callable
... 我看了一下 at-at
,不幸的是它似乎也没有在其 fn 参数中包装 try-catch-printstacktrace - berdario"tools.timer" 库是一个 Java Timer 包装器:https://github.com/Ruiyun/tools.timer
它非常容易使用:
(use 'ruiyun.tools.timer)
(run-task! #(println "Say hello every 5 seconds.") :period 5000)
overtone/at-at
! - djhworldovertone/at-at
在过去几个月似乎有些被忽视了,这个 fork 可能会很有意思:https://github.com/silasdavis/at-at - berdario