Использование агентов для синхронизации заданий - PullRequest
6 голосов
/ 14 августа 2011

Я играю с симуляцией, в которой у меня есть пара роботов и контроллер, контроллер решил, что делать, и назначил задания роботам. Следующее это технически нарушение, в основном меня не волнует состояние агентов, я просто забочусь о факт, что он выполнит отправленные ему 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 или мне нужно повторно реализовать структуру, подобную агенту?

1 Ответ

6 голосов
/ 15 августа 2011

Вы можете отправить или отослать из действия агента все, что вам нравится.

То, что вы на самом деле не можете сделать, - это ожидание завершения другим агентом внутри агента. Как говорится в сообщении.

Это хорошовещь, поскольку разрешение ждать в агенте, очевидно, приводит к возможным тупикам.Смысл примитивов параллелизма clojure состоит в том, чтобы сделать тупик (и другие проблемы, связанные с параллелизмом) невозможным, если вы играете по правилам.

IMO ваш вариант использования не идеален для агентов.Они предназначены для асинхронной точки синхронизации, аналогичной части inbox queue действующих лиц.Поскольку вам не нужны эти возможности и вы используете их в качестве простых исполнителей заданий, я думаю, вам будет лучше работать с простой Java ExecutorService .

Также может представлять интерес Платформа ForkJoin , которая в основном заключается в том, чтобы отбрасывать небольшие единицы вычислений по ходу работы и (возможно) ждать их в тот момент, когда вам нужен результат.

...