2011-08-14 6 views
6

Mi sto trastullando con una simulazione in cui ho un paio di robot e un controller, il controller ha deciso cosa fare e assegnare i lavori ai robot, in seguito è tecnicamente un abuso fondamentalmente non mi interessa lo stato degli agenti, Mi interessa solo il fatto che eseguirà i fns inviati in ordine e posso aspettare che finiscano.Uso degli agenti per sincronizzare i lavori

seguito praticamente dimostra quello che sto cercando di realizzare, controllore ottiene un grande lavoro ogni robot ottiene un pezzo di esso,

 

(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... 
      )) 
 

Bene il problema è che non è possibile inviare-off all'interno di un Invia- fuori ricevo "Non posso aspettare in azione agente". È possibile farlo usando gli strumenti di concorrenza di clojure o devo implementare nuovamente una struttura come agente?

risposta

6

È possibile inviare o inviare da un'azione dell'agente tutto ciò che si desidera.

Quello che non si può, infatti, fare, è attendono per un altro agente per completare, dall'interno di un agente. Proprio come dice il messaggio.

Questa è una buona cosa, poiché consentire di attendere in un agente porta ovviamente a possibili blocchi. Il punto delle primitive della concurrency clojure è quello di rendere impossibile il deadlock (e altri problemi relativi alla concorrenza), se si rispettano le regole.

IMO il tuo caso d'uso non è l'ideale per gli agenti. Sono pensati per essere un punto di sincronizzazione asincrono, simile alla parte di attori inbox queue. Dal momento che non hai bisogno di quella capacità e li usi come meri corridori di lavoro, penso che ti verrà servito meglio con un semplice Java ExecutorService.

Anche di interesse potrebbe essere il framework ForkJoin, che fondamentalmente consiste nel biforcarsi piccole unità di un calcolo mentre si va e (eventualmente) nell'attenderle nel momento in cui si ha bisogno del risultato.