在Clojure中,在条件成立之前,如何阻止线程(未来)?或者,或许,可能会继续重试,直到条件成立为止?当你有条件变量时这很容易,但我不确定Clojure的方法是什么。
更具体地说,我有一个共享变量,可以同时被许多期货访问。未来应该做到以下几点:
答案 0 :(得分:1)
Java平台支持条件变量,请参阅java.util.concurrent.locks.Condition
的文档。
上页中的示例很容易转换为Clojure:
;;; based on the example in java.util.concurrent.locks.Condition
;;; documentation for JDK 1.7, see the link above
(defprotocol PBoundedBuffer
(-put [buf x])
(-take [buf]))
(import (java.util.concurrent.locks ReentrantLock Condition))
(deftype BoundedBuffer [^ReentrantLock lock
^Condition not-full?
^Condition not-empty?
^objects items
^:unsynchronized-mutable ^int putptr
^:unsynchronized-mutable ^int takeptr
^:unsynchronized-mutable ^int cnt]
PBoundedBuffer
(-put [buf x]
(.lock lock)
(try
(while (== cnt (alength items))
(.await not-full?))
(aset items putptr x)
(set! putptr (unchecked-inc-int putptr))
(if (== putptr (alength items))
(set! putptr (int 0)))
(set! cnt (unchecked-inc-int cnt))
(.signal not-empty?)
(finally
(.unlock lock))))
(-take [buf]
(.lock lock)
(try
(while (zero? cnt)
(.await not-empty?))
(let [x (aget items takeptr)]
(set! takeptr (unchecked-inc-int takeptr))
(if (== takeptr (alength items))
(set! takeptr (int 0)))
(set! cnt (unchecked-dec-int cnt))
(.signal not-full?)
x)
(finally
(.unlock lock)))))
(defn bounded-buffer [capacity]
(let [lock (java.util.concurrent.locks.ReentrantLock.)]
(BoundedBuffer. lock
(.newCondition lock)
(.newCondition lock)
(object-array capacity)
0
0
0)))
REPL的试驾:
(def bb (bounded-buffer 3))
(-put bb 1)
(-put bb 2)
(-put bb 3)
(future (-put bb 4) (println :foo))
(-take bb)
根据需要,未来阻止,然后在最后一次调用:foo
后打印-take
。
答案 1 :(得分:0)
答案 2 :(得分:0)
您可以存储您在代理中检查的条件或值,并添加一个在条件变为true
时执行所需操作的手表,或者值是您想要的值:
(def x (agent 0))
(defn do-this-once-x-is-10 [key agnt old-val new-val]
(when (= new-val 10)
(println "x is now 10")))
(add-watch x :print-alert do-this-once-x-is-10)
(dotimes [_ 10]
(Thread/sleep 1000)
(send x inc))
; the value stored in x is incremented every second; after 10 seconds,
; the value of x will equal 10 and "x is now 10" will print