2011-09-12 7 views
4

私は、リクエスト(スレッド)で特定の関数が呼び出された回数を追跡できるようにするWebアプリケーションを用意しています。Clojureのスレッドローカルカウンタ

refを使って非スレッドのローカル方法で行うことができますが、ローカルでスレッドを実行するにはどうすればよいですか?

答えて

10

を参照してください

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

:しようと、証明するために

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

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

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

:以下は*counter*私-FNがwith-counter呼び出し内で呼ばれる任意の形式のために呼び出されるたびに増加しますusefulにはthread-localというツールがあります。例えば、(def counter (thread-local (atom 0)))と書くことができます。これにより、グローバル変数が作成されます。derefにすると、スレッドごとに新しいアトムが生成されます。だから、@@counterで現在の値を読むか、(swap! @counter inc)でそれを増やすことができます。もちろん、あなたはまた、@counterで原子そのものを保持し、それからそれを通常の原子のように扱うことができます。

-1

ref31にThreadLocalのインスタンスを保存することができます。そして、あなたがそれを増やす必要があるたびに、値を読んで、それを増やして戻してください。リクエストの開始時には、スレッドが異なる要求に対して再利用できるため、0のスレッドローカルを初期化する必要があります。

+2

確かに、ThreadLocalでの参照は他の方法より簡単ですか?私は、ThreadLocalが変更可能であり、refと調整されていないため、refにThreadLocalを保持することが理にかなっていません。とにかくそれらの再試行されたトランザクションが中断します。 – amalloy

7

bindingの値にバインドされた動的グローバル変数を使用して、特殊フォームset!と組み合わせて値を変更することができます。 bindingでバインドされたバールはスレッドローカルです。 http://clojure.org/vars#set