Clojure实现带超时的期货向量

Clojure realize vector of futures with timeout

我正在连接一个 Java API 那个 returns 一个 CompletableFuture。 现在,如果我有这些 [cf1 cf2 cf3 …] 的数组,我如何给它们 all 一秒完成,并在一秒后收集它们产生的任何东西?

类似于:

  (def vec-of-cf [cf1 cf2 cf3])

  (get-all vec-of-cf 1000 ::timeout)

  ;; no more than 1 second later, I should have my vector of realized CompletableFuture, possibly holding a `::timeout` value if they did not have time to finish

我认为这类似于 Scala flatmap (?).

像这样的东西应该可以工作:

(defn get-all [vec-of-cf timeout timeout-val]
 (Thread/sleep timeout)
 (mapv #(if (future-done? %) (deref %) timeout-val) vec-of-cf))

也可以修改此代码以取消未完成的未来(如果需要)

您可以使用 CompletableFuture.allOf 来获得一个可完成的未来,您可以阻塞等待所有任务完成或超时所需的时间(因此等待时间可能短于超时时间 - 所有任务都已完成到一秒,不一定在一秒之后),然后迭代原始期货以获得它们的价值(如果完成):

(def vec-of-cf [cf1 cf2 cf3])

(let [all-of (CompletableFuture/allOf (into-array vec-of-cf))]
  (try
    (.get all-of timeout)
    (catch java.util.concurrent.TimeoutException e))
  (->> vec-of-cf
       (filter #(.isDone %))
       (map #(.get %))))