2011-09-12 49 views
4

我有一個web應用程序,我希望能夠跟蹤一個給定函數在請求(即線程)中被調用的次數。Clojure中的Threadlocal計數器

我知道有可能以ref的方式以非線程本地方式進行,但我該如何去做本地線程?

回答

10

useful中有一個叫做thread-local的工具。你可以寫,例如,(def counter (thread-local (atom 0)))。這將創建一個全局變量,當編輯deref時,會產生每個線程的新鮮原子。所以你可以用@@counter讀取當前值,或者用(swap! @counter inc)增加它。當然,你也可以使用@counter來掌握原子本身,並將它當作普通原子。

-1

您可以參考ThreadLocal的實例。每次你需要增加它時,只要讀取它的價值,增加它並讓它恢復原狀。在請求開始時,您應該使用0初始化本地線程,因爲線程可能會被重用於不同的請求。

+2

確實在ThreadLocal中保留一個ref比其他方式更容易?我不確定在參考文獻中保留一個ThreadLocal是否合理,因爲ThreadLocals是可變的,並且不與refs協調;反正他們的交易會破壞。 – amalloy

7

您可以結合使用動態全局變量,綁定到一個值與binding與特殊形式set!來改變其值。與binding綁定的變量是線程本地的。下面將每次增加*counter*我-FN被稱爲用於任何形式稱爲with-counter調用中:

(def ^{:dynamic true} *counter*) 

(defmacro with-counter [& body] 
    `(binding [*counter* 0] 
    [email protected] 
    *counter*)) 

(defn my-fn [] 
    (set! *counter* (inc *counter*))) 

爲了演示,請嘗試:

(with-counter (doall (repeatedly 5 my-fn))) 
;; ==> 5 

欲瞭解更多信息,請參閱http://clojure.org/vars#set