一周前,我问了一个类似的问题(Link),在那里我了解到地图的懒惰特性使得以下代码顺序运行。
(defn future-range
[coll-size num-futures f]
(let [step (/ coll-size num-futures)
parts (partition step (range coll-size))
futures (map #(future (f %)) parts)] ;Yeah I tried doall around here...
(mapcat deref futures)))
这是有道理的。但是我该如何解决呢?我几乎尝试了所有的东西(:D),一种与承诺和许多其他事物不同的方法。它只是不想工作。为什么?在我看来,在mapcat derefs之前,期货才会开始(我用Thread / sleep进行了一些测试)。但是当我完全意识到doall的序列不应该在另一个线程中立即开始期货?
答案 0 :(得分:2)
看来你已经在那里了。如果你将(map #(future (f %)) parts)
包裹在(doall ...)
中,它就可以了。只需重新启动您的repl并从干净的平板开始,以确保您正在调用正确的函数版本。
(defn future-range
[coll-size num-futures f]
(let [step (/ coll-size num-futures)
parts (partition step (range coll-size))
futures (doall (map #(future (f %)) parts))]
(mapcat deref futures)))
您可以使用以下方法对其进行测试。
(defn test-fn [x]
(let [start-time (System/currentTimeMillis)]
(Thread/sleep 300)
[{:result x
:start start-time
:end-time (System/currentTimeMillis)}]))
(future-range 10 5 test-fn)
您也可以使用time
来衡量5次(Thread/sleep 300)
只需要300毫秒的时间:
(time (future-range 10 5 (fn [_] (Thread/sleep 300))))