【问题标题】:Time for control flow in Clojure - pitfalls of ScheduledThreadPoolExecutor?Clojure 中控制流的时间——ScheduledThreadPoolExecutor 的陷阱?
【发布时间】:2012-08-16 18:57:15
【问题描述】:

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

我在http://dev.clojure.org/display/design/Scheduled+Events 遇到了一个索赔(Stuart Serra?),声明:

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

我不明白这些说法,恳请澄清,也许是一个例子。具体来说:

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

非常感谢!

【问题讨论】:

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


    【解决方案1】:

    好的,我想我明白了。

    假设你试试这个:

    (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 宏用私有函数 binding-conveyor-fn 包装主体,它将调用线程的绑定框架保留在词法范围内,并在调用包装函数之前恢复它。

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

    在第二种情况下,没有人保存每个线程的绑定——Java 类当然不知道它们,所以我们将其放到 t Var 的根值。

    我希望有人会觉得这很有趣。

    【讨论】:

      猜你喜欢
      • 2014-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-22
      • 1970-01-01
      • 2014-08-11
      相关资源
      最近更新 更多