Clojure中控制流的时间 - ScheduledThreadPoolExecutor的陷阱?

时间:2012-08-16 18:57:16

标签: clojure scheduled-tasks clojure-java-interop

我正在学习Clojure中的并发性。

我在http://dev.clojure.org/display/design/Scheduled+Events遇到了一个声明(斯图尔特塞拉?)声明:

  
      
  • Clojure函数无法在没有阻塞或Java互操作的情况下将时间用于控制流程
  •   
  • Java interop(ScheduledThreadPoolExecutor)不知道线程局部绑定
  •   

我不理解这些说法并请求澄清,也许是一个例子。具体做法是:

  • ScheduledThreadPoolExecutor有什么问题?因为我正在开始一个新的(绿色)线程,所以我不希望每个线程的绑定继续进行。
  • 我可以安排一个普通的Clojure函数,那么是什么阻止我发送所需的绑定作为词汇封闭的上下文?

非常感谢!

1 个答案:

答案 0 :(得分:4)

好的,我想我明白了。

假设你试试这个:

(def pool (atom nil))

(defn- thread-pool []
    (or @pool
        (reset! pool (ScheduledThreadPoolExecutor. 1))))

(def ^:dynamic *t* 0)

(binding [*t* 1]
    (future (println "first example:" *t*)))

(binding [*t* 1]
    (.schedule (thread-pool) (fn [] (println "second example:" *t*)) 0 
               TimeUnit/SECONDS))

(binding [*t* 1]
    (.schedule (thread-pool) (bound-fn [] (println "third example:" *t*)) 0
               TimeUnit/SECONDS))

输出将是:

first example: 1
second example: 0
third example: 1

在第一种情况下,未来的宏用私有函数binding-conveyor-fn包装主体,它保留了词法范围内的调用线程的绑定帧,并在调用包装函数之前恢复它。

在第三种情况下,bound-fn将调用线程的绑定推送到帧上,执行函数体,然后弹出绑定。

在第二种情况下,没有人保存每个线程的绑定 - 一个Java类肯定不知道它们,所以我们下降到 t Var的根值。

我希望那里有人觉得这很有意思。