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

我在http://dev.clojure.org/display/design/Scheduled+Events上遇到了(由Stuart Serra?)提出的要求,并指出:


  • Clojure函数无法在没有阻塞或Java互操作的情况下使用时间进行控制流
  • Java interop(ScheduledThreadPoolExecutor)不了解线程本地绑定(bind)


  • 我不理解这些主张,请澄清一下,也许是一个例子。特别:
  • ScheduledThreadPoolExecutor怎么了?由于我正在启动新的(绿色)线程,因此我不希望每线程绑定(bind)继续执行。
  • 我可以安排正常的Clojure函数,那么是什么阻止了我将期望的绑定(bind)作为词法关闭的上下文发送呢?

  • 非常感谢!

    最佳答案

    好吧,我想我明白了。

    假设您尝试以下操作:

    (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
    

    在第一种情况下,future宏使用 private 函数binding-conveyor-fn包裹主体,该 private 函数将调用线程的绑定(bind)框架保留在词法范围内,并在调用包裹的函数之前对其进行恢复。

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

    在第二种情况下,没有人保存每个线程的绑定(bind)-Java类当然不知道它们,因此我们使用了t Var的根值。

    我希望那里的人觉得这很有趣。

    10-07 19:01
    查看更多