据我所知,Clojure中的pmap
就像map
一样,但它使用期货来平行计算结果。因此,如果map
与它们一起使用,它应该“正常”使用函数和序列。 (除非存在阻止它的邪恶副作用,但是在我的程序中,只有从http服务器加载数据并对其进行转换)
在我的情况下,pmap
无法按预期工作。为什么会发生这种情况?
此处出现问题(如果我将map
更改为pmap
):
https://github.com/magicgoose/DvachMaster/blob/master/src/dvach/core.clj#L82
(defn thread-list
"load threads from all pages, trying each page at most `max-trials` times with `retry-inteval`"
[board]
(try
(let [p0 (load-body (board-addr board 0))
numpages (count (:pages p0))
other-pages (map ; problem here
(comp
load-body
(partial board-addr board))
(range 1 numpages))
all-pages (cons p0 other-pages)
]
(doall
((comp (partial reduce concat) (partial map :threads)) all-pages)))
(catch Throwable e
(.printStackTrace e))))
我得到的例外:
java.util.concurrent.ExecutionException: java.lang.ClassCastException: java.lang.Long cannot be cast to java.util.concurrent.Future
at java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source)
at java.util.concurrent.FutureTask.get(Unknown Source)
at clojure.core$deref_future.invoke(core.clj:2108)
at clojure.core$future_call$reify__6267.deref(core.clj:6308)
at clojure.core$deref.invoke(core.clj:2128)
at clojure.core$pmap$step__6280$fn__6282.invoke(core.clj:6358)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:60)
at clojure.lang.RT.seq(RT.java:484)
at clojure.core$seq.invoke(core.clj:133)
at clojure.core$map$fn__4207.invoke(core.clj:2479)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:60)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.next(RT.java:598)
at clojure.core$next.invoke(core.clj:64)
at clojure.core.protocols$fn__6034.invoke(protocols.clj:146)
at clojure.core.protocols$fn__6005$G__6000__6014.invoke(protocols.clj:19)
at clojure.core.protocols$seq_reduce.invoke(protocols.clj:27)
at clojure.core.protocols$fn__6026.invoke(protocols.clj:53)
at clojure.core.protocols$fn__5979$G__5974__5992.invoke(protocols.clj:13)
at clojure.core$reduce.invoke(core.clj:6175)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.AFn.applyTo(AFn.java:151)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$partial$fn__4190.doInvoke(core.clj:2396)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$comp$fn__4154.invoke(core.clj:2331)
at dvach.core$thread_list.invoke(core.clj:91)
at dvach.core$eval3813.invoke(NO_SOURCE_FILE:2)
at clojure.lang.Compiler.eval(Compiler.java:6619)
at clojure.lang.Compiler.eval(Compiler.java:6582)
at clojure.core$eval.invoke(core.clj:2852)
at clojure.main$repl$read_eval_print__6588$fn__6591.invoke(main.clj:259)
at clojure.main$repl$read_eval_print__6588.invoke(main.clj:259)
at clojure.main$repl$fn__6597.invoke(main.clj:277)
at clojure.main$repl.doInvoke(main.clj:277)
at clojure.lang.RestFn.invoke(RestFn.java:1096)
at clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__1023.invoke(interruptible_eval.clj:56)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.AFn.applyTo(AFn.java:151)
at clojure.core$apply.invoke(core.clj:617)
at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1788)
at clojure.lang.RestFn.invoke(RestFn.java:425)
at clojure.tools.nrepl.middleware.interruptible_eval$evaluate.invoke(interruptible_eval.clj:41)
at clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__1064$fn__1067.invoke(interruptible_eval.clj:171)
at clojure.core$comp$fn__4154.invoke(core.clj:2330)
at clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__1057.invoke(interruptible_eval.clj:138)
at clojure.lang.AFn.run(AFn.java:24)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassCastException: java.lang.Long cannot be cast to java.util.concurrent.Future
at clojure.core$deref_future.invoke(core.clj:2108)
at clojure.core$deref.invoke(core.clj:2129)
at dvach.core$load_body.invoke(core.clj:74)
at clojure.core$comp$fn__4154.invoke(core.clj:2331)
at clojure.core$pmap$fn__6275$fn__6276.invoke(core.clj:6354)
at clojure.core$binding_conveyor_fn$fn__4107.invoke(core.clj:1836)
at clojure.lang.AFn.call(AFn.java:18)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
... 3 more
答案 0 :(得分:2)
堆栈跟踪抱怨的问题是第74行的@max-trials
;这应该是max-trials
而不是max-trials
。 (@retry-count
是一个在第66行初始化为try
的循环变量;它将是一个数字,然后在每次迭代时递减。)
它可能会间歇性地出现,因为只有在第68行开始的{{1}}块无法获取结果时才会达到代码中的那一点。