如何将Clojure的in-thread函数改为宏实现Claypoole线程池延迟执行
问题:如何用Clojure宏实现代码体在线程池延迟执行
需求是通过claypoole库将代码作为future提交到目标线程池,让代码在线程中执行而非调用时立即求值。
现有函数版实现:
(defn in-thread [thread & body] (claypoole/future thread body))
调用代码:
(defonce pool (claypoole/threadpool 20)) (defn do-something [pool] (in-thread pool (Thread/sleep 5000) (println "foo")))
测试发现,代码体在调用in-thread时就已被求值,无法达到预期效果。
原因分析
Clojure函数调用时会先求值所有参数,所以body里的代码在传给in-thread函数之前就已经执行了,这就是为什么Thread/sleep和println会立刻运行。而宏是在编译期展开,不会提前求值参数,正好能解决这个问题。
解决方案:改为宏实现
将in-thread定义为宏,利用语法引用和解引用,把body的代码片段原封不动地传递给claypoole/future,让它在线程池中执行:
(defmacro in-thread [thread & body] `(claypoole/future ~thread (do ~@body)))
代码解释
- 反引号
`用于语法引用,避免符号被解析成当前命名空间的符号; ~thread是解引用,把传入的线程池变量正确代入宏展开后的代码;~@body是拼接多个表达式,把body里的所有代码放到do块中,保证多个表达式能顺序执行;- 宏展开后,最终生成的代码是
(claypoole/future pool (do (Thread/sleep 5000) (println "foo"))),claypoole/future会把do块作为任务提交到线程池,在线程中执行,不会提前求值。
测试验证
调用代码无需修改,执行(do-something pool)后,Thread/sleep和println会在线程池的线程中延迟5秒执行,而非调用时立刻运行。
内容的提问来源于stack exchange,提问作者kelly
相关产品推荐
相关产品推荐

