Clojure中的线程本地计数器
我有一个web应用程序,我希望能够跟踪给定函数在请求中被调用的次数(即线程)Clojure中的线程本地计数器,clojure,thread-local,Clojure,Thread Local,我有一个web应用程序,我希望能够跟踪给定函数在请求中被调用的次数(即线程) 我知道可以使用ref以非线程本地方式执行,但如何在线程本地执行呢?您可以将的实例保留在ref中。每次需要增加它时,只需增加它的读取值,增加它并返回。在请求开始时,您应该使用0初始化线程本地,因为线程可能会被重新用于不同的请求。您可以使用动态全局变量,绑定到带有绑定的值,并结合特殊的集合以更改其值。与绑定的变量是线程本地变量。每次调用带有计数器的调用中调用的任何形式的my fn时,以下内容将增加*计数器*: (def ^
我知道可以使用ref以非线程本地方式执行,但如何在线程本地执行呢?您可以将的实例保留在ref中。每次需要增加它时,只需增加它的读取值,增加它并返回。在请求开始时,您应该使用0初始化线程本地,因为线程可能会被重新用于不同的请求。您可以使用动态全局变量,绑定到带有
绑定的值,并结合特殊的集合
以更改其值。与绑定的变量是线程本地变量。每次调用带有计数器的调用中调用的任何形式的my fn时,以下内容将增加*计数器*
:
(def ^{:dynamic true} *counter*)
(defmacro with-counter [& body]
`(binding [*counter* 0]
~@body
*counter*))
(defn my-fn []
(set! *counter* (inc *counter*)))
要演示,请尝试:
(with-counter (doall (repeatedly 5 my-fn)))
;; ==> 5
有关更多信息,请参见在线程本地中有一个用于此的工具。例如,您可以编写(def计数器(线程本地(atom 0))
。这将创建一个全局变量,当deref
ed时,该变量将为每个线程生成一个新的原子。因此,您可以使用@@counter
读取当前值,或使用(swap!@counter inc)
增加当前值。当然,您也可以使用@counter
控制原子本身,并从那时起将其视为普通原子。在ThreadLocal中保留一个ref肯定比另一种方法更容易吗?我不确定在ref中保留ThreadLocal是否有意义,因为ThreadLocal是可变的,并且不与ref协调;对它们重试的事务仍将中断。这仅在宏的上下文中有效。如果您的代码不是调用方(如ring或HTTP服务器调用您的代码来处理请求),那么它将无法工作。例如:修改(def
如下:(def^{:dynamic true}*counter*10)
执行(使用计数器,然后检查计数器:(使用计数器(doall(重复5 my fn))。=>5
*计数器*=>10