6

我正在玩一个模拟,其中我有几个机器人和一个控制器,控制器决定做什么并将工作分配给机器人,从技术上讲,以下是一种滥用,基本上我不关心代理状态,我只关心它的事实将按顺序执行发送给它的 fns,我可以等待它们完成。

以下几乎展示了我想要实现的目标,控制器得到了很大的工作,每个机器人都得到了一大块,


(def *agents* (reduce
               (fn[h v] (assoc h v (agent true)))
               {:control (agent true)} (range 0 5)))

(defn send-job [id f]
  (send-off (*agents* id)
            (fn [s f]
              (try
                (f)
                (catch Exception e (println e))))
            f))

(defn await-job [id]
  (await (*agents* id)))

(send-job :control
          (fn []

            (send-job 0 (fn []
                          (Thread/sleep 10)
                          (println "0 Done.")))

            (send-job 1 (fn []
                          (Thread/sleep 2)))

            (await-job 1)
            ;; 0 still running.
            ;; do other stuff...
            ))

好吧,问题是你不能在送行中送行,我得到“不能在代理行动中等待”。是否可以使用 clojure 的并发工具来做到这一点,或者我是否必须重新实现类似结构的代理?

4

1 回答 1

6

您可以随心所欲地在代理操作中发送或发送。

实际上,您不能做的是等待另一个代理完成,从代理内部完成。就像消息说的那样。

这是一件好事,因为允许在代理中等待显然会导致可能的死锁。如果您遵守规则,clojure 并发原语的要点是使死锁(和其他与并发相关的问题)成为不可能。

IMO 您的用例不适合代理。它们是一个异步的同步点,类似于inbox queue参与者的部分。由于您不需要该功能并将它们仅用作工作运行者,因此我认为使用普通的 Java ExecutorService会为您提供更好的服务。

同样令人感兴趣的可能是ForkJoin框架,它基本上是关于在你进行时分叉计算的小单元,并且(可能)在你需要结果的那一刻等待它们。

于 2011-08-15T08:45:12.987 回答