Concurrency Clojure删除ref中向量的第一个(或最后一个)元素
我需要的是一个简单的队列,在这里我可以放置任务,并从工作人员那里一个接一个地检索它们(无需维护任务的顺序) 我写了这样的东西:Concurrency Clojure删除ref中向量的第一个(或最后一个)元素,concurrency,clojure,atomicity,Concurrency,Clojure,Atomicity,我需要的是一个简单的队列,在这里我可以放置任务,并从工作人员那里一个接一个地检索它们(无需维护任务的顺序) 我写了这样的东西: ;; Definition (def q (ref [])) ;; Put (defn put-in-queue [i] (dosync (alter q conj i))) ;; Get (defn get-from-queue [] (dosync (let [v (peek q)] (alter q pop) v)))
;; Definition
(def q (ref []))
;; Put
(defn put-in-queue [i]
(dosync (alter q conj i)))
;; Get
(defn get-from-queue []
(dosync
(let [v (peek q)]
(alter q pop)
v)))
这是正确的解决方案吗?(可能还有更好的解决方案)您应该使用
clojure.lang.PersistentQueue
,这是一个适合该作业的工具,以及所有这些:)
以下样本“借用”自:
请参阅以了解详细信息。正如dsm所指出的,当您需要队列时,请使用队列,对于确实需要向量并希望在末尾添加内容并从前面删除内容的情况,
subvec
和conj
都是向量上的O(1)函数
user> (subvec [1 2 3] 1)
[2 3]
user> (conj [1 2 3] 4)
[1 2 3 4]
user> (-> [] (conj 1 2) (conj 3) (subvec 1))
正确的解决方案很可能是使用
java.util.concurrent
队列j.u.c
队列非常健壮,非常适合任务,在Clojure中工作也很好
对于5个生产者、2个消费者和以两种方式实现的有限大小队列的场景,请参见SO问题,以进行比较:首先是使用
c.l.PersistentQueue
,其次是使用j.u.c.LinkedBlockingQueue
,问题是关于多线程环境的,不只是使用subvec。clojure.core/subvec
保留基础向量,因此这将防止所有条目无限期地符合GC的条件。(与此相反,clojure.core.rrb vector/subvec
执行实际切片,丢弃给定索引范围之外的条目。)
user> (subvec [1 2 3] 1)
[2 3]
user> (conj [1 2 3] 4)
[1 2 3 4]
user> (-> [] (conj 1 2) (conj 3) (subvec 1))