2

据我所知,pmap在 Clojure 中的工作方式与 类似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
4

1 回答 1

2

堆栈跟踪抱怨的问题@max-trials在第 74 行;这应该改为阅读max-trials。(max-trials是在第 66 行初始化为的循环变量@retry-count;然后它将是一个数字,每次迭代都会递减。)

try它很可能会间歇性地出现,因为只有在第 68 行开始的块未能获取结果时才会到达代码中的那个点。

于 2013-05-18T17:03:09.710 回答