如何在单线程中执行一些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

回到顶部