如何在单线程中执行一些Clojure期货?
我想在Clojure中创建一些未来,并在特定的线程上运行它们,以确保它们一次运行一次。这可能吗?如何在单线程中执行一些Clojure期货?
将Java库包装起来并不难,但在这之前我想确保我不会错过Clojure的做法。在Java中,我可以通过执行FutureTask
并将这些任务提交给单线程执行程序来执行此操作。
回答:
Clojure的future macro调用future-call功能使用a dedicated executor service。这意味着您无法控制执行顺序执行。
在另一方面,你可以使用的promise代替future
对象,一个future
线程顺序deliver结果。 Promise的API与future
提供的相似。他们也有deref和realized?。
以下代码示例具有在后台的新线程中按顺序执行的子任务,而函数的立即返回结果包含对计算值的承诺。
(defn start-async-calc [] (let [f1 (promise)
f2 (promise)
f3 (promise)]
(future
(deliver f1 (task-1))
(deliver f2 (task-2))
(deliver f3 (task-3)))
{:task1 f1
:task2 f2
:task3 f3}))
回答:
,如果你想sequentialize到future
来电您可以手动使用它像这样:
(do @(future 1) @(future 2)
@(future 3))
他们仍然可能被称为在不同的线程,但下一个会不会被调用,直到之前已完成。这由@
(或deref
函数)保证。这意味着执行do
表单的线程在完成之前将被prev承诺阻塞,然后产生下一个。
你可以用宏美化这样的:
(defmacro sequentialize [& futures] `(do [email protected](map #(list `deref %) futures)))
user> (let [a (atom 1)]
(sequentialize
(future (swap! a #(* 10 %)))
(future (swap! a #(+ 20 %)))
(future (swap! a #(- %))))
@a)
;;=> -30
这样做完全一样的手动do
。请注意,突变a
原子是有序即使某些线程运行的时间更长:
user> (let [a (atom 1)] (sequentialize
(future (Thread/sleep 100)
(swap! a #(* 10 %)))
(future (Thread/sleep 200)
(swap! a #(+ 20 %)))
(future (swap! a #(- %))))
@a)
;;=> -30
回答:
Manifold提供一种方式来创造未来with specific executor。它不是核心Clojure库的一部分,但它仍然是一个高质量的库,如果你需要更多的灵活性来处理未来,而不是核心lib提供的(而不是采用Java interop),那么这可能是一个最好的选择。
回答:
另外提到的promises
,您可以使用delay
。承诺的问题是您可能无意中无法提供它们,并创建一个死锁场景,这是future
s和delay
s不可能实现的。未来和延迟之间的差异只是工作执行的线索。未来,这项工作是在后台完成的,并且延迟工作是由第一个尝试解除它的线程完成的。因此,如果未来的是一个比承诺更合适,你总是可以这样做:
(def result-1 (delay (long-calculation-1))) (def result-2 (delay (long-calculation-2)))
(def result-3 (delay (long-calculation-3)))
(defn run-calcs []
@(future
@result-1
@result-2
@result-3))
以上是 如何在单线程中执行一些Clojure期货? 的全部内容, 来源链接: utcz.com/qa/267388.html