dictionary - 在我的 Clojure 程序中将 map 更改为 pmap 会导致奇怪的异常 (ClassCastException)

标签 dictionary clojure future

据我所知,Clojure 中的 pmap 的工作方式与 map 类似,但它在底层使用 futures 并行计算结果。因此,如果 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

最佳答案

堆栈跟踪提示的问题是第 74 行的 @max-Trials;这应该改为max-Trials。 (max-Trials 是一个循环变量,在第 66 行初始化为 @retry-count;它将是一个数字,在每次迭代时递减。)

它很可能会间歇性地出现,因为只有当从第 68 行开始的 try block 无法获取结果时,才会到达代码中的该点。

关于dictionary - 在我的 Clojure 程序中将 map 更改为 pmap 会导致奇怪的异常 (ClassCastException),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16626723/

相关文章:

python - 使用python对字符串中的单词进行加权计数

clojure - 如何从 Clojure 获取 Java 类的方法?

Clojure 项目值得一读吗?

clojure - 如何在 Kotlin 中运行 Clojure?

c++ - 如何在 C++ 中的 boost::future 中添加回调

c# - c# 中的 const 字典

c# - ConcurrentDictionary 多次添加相同的键

java - 如何在迭代时从 HashMap 中删除一个键?

c++ - 在 C++ 中解压参数包