Threadlocal counter in Clojure
I have a web app where i want to be able to track the number of times a given function is called in a request (i.e. thread).
I know that it is possible to do in a non-thread local way with a ref, but how would I go about d开发者_如何学JAVAoing it thread locally?
There's a tool for this in useful called thread-local
. You can write, for example, (def counter (thread-local (atom 0)))
. This will create a global variable which, when deref
ed, will yield a fresh atom per thread. So you could read the current value with @@counter
, or increment it with (swap! @counter inc)
. Of course, you could also get hold of the atom itself with @counter
and just treat it like a normal atom from then on.
You can use a dynamic global var, bound to a value with binding
in combination with the special form set!
to change its value. Vars bound with binding
are thread-local. The following will increase *counter*
every time my-fn is called for any form called within a with-counter
call:
(def ^{:dynamic true} *counter*)
(defmacro with-counter [& body]
`(binding [*counter* 0]
~@body
*counter*))
(defn my-fn []
(set! *counter* (inc *counter*)))
To demonstrate, try:
(with-counter (doall (repeatedly 5 my-fn)))
;; ==> 5
For more information, see http://clojure.org/vars#set
You can keep instance of ThreadLocal in ref. And every time you need to increase it just read value, increase it and set back. At the beginning of request you should initialize thread local with 0, because threads may be reused for different requests.
精彩评论