如何启动两个线程并等待它们

oct*_*bus 2 clojure

我可以启动两个线程,但它们可以同步工作.为了让这些线程独立发布,我缺少什么?

主,线程和输出

(defn -main 
    [& args]
    (do
        (let [grid-dim-in [0 5]
              mr1-pos     [\N 2 4]
              mr2-pos     [\N 1 5]
              mr1-movs    "LMLMMRMM"
              mr2-movs    "RMRMMMLM"]

            (reset! grid-dim grid-dim-in)
            (reset! mr1-id {:mr1 mr1-pos})
            (reset! mr2-id {:mr2 mr2-pos})

            (.start (Thread. (rover-thread mr1-id mr1-movs update-work-block)))
            (.start (Thread. (rover-thread mr2-id mr2-movs update-work-block))))))

(defn rover-thread [id movs update-ref]
    (let [id-key (keys @id)
          id-vals (vals @id)]
        (doseq [mov movs]
           (println "Rover " id-key " is moving ")
           (let [new-mov (determine-rover-move (first id-vals) mov)]
               (move-rover id new-mov update-ref)
               (print "Rover ")
               (print (first id-key))
               (print " is at ")
               (println new-mov)
               (Thread/sleep (rand 1000)))))

Rover :mr1 is at [E 2 4]
Rover  (:mr1)  is moving 
Rover :mr1 is at [N 2 5]
Rover  (:mr1)  is moving 
Rover :mr1 is at [N 2 5]
Finished on Thread[main,5,main]
Rover  (:mr2)  is moving 
Rover :mr2 is at [E 1 5]
Rover  (:mr2)  is moving 
Rover :mr2 is at [N 1 6]
Run Code Online (Sandbox Code Playgroud)

Ger*_*ert 7

仔细看看这两行:

(.start (Thread. (rover-thread mr1-id mr1-movs update-work-block)))
(.start (Thread. (rover-thread mr2-id mr2-movs update-work-block))))))
Run Code Online (Sandbox Code Playgroud)

此代码计算第(rover-thread mr1-id mr1-movs update-work-block)一个,并将结果传递给构造函数Thread,这不是您想要的.

这是一个简单的函数来说明原理.这不起作用,因为(f ...)在将结果传递给Thread构造函数之前对其进行求值:

(defn run-thread-thing-wrong []
  (let [f (fn [n s]
            (doseq [i (range n)]
              (prn s i)
              (Thread/sleep (rand 1000))))]
    (.start (Thread. (f 10 "A")))
    (.start (Thread. (f 10 "B"))))
  nil)
Run Code Online (Sandbox Code Playgroud)

这是一个有效的版本.一个函数传递给Thread构造函数来代替:

(defn run-thread-thing []
  (let [f (fn [n s]
            (doseq [i (range n)]
              (prn s i)
              (Thread/sleep (rand 1000))))]
    (.start (Thread. (fn [] (f 10 "A"))))
    (.start (Thread. (fn [] (f 10 "B")))))
  nil)
Run Code Online (Sandbox Code Playgroud)

注意:代替(fn [] ....)您可以使用简短形式#(....)进行匿名功能.

这是另一个版本相同,但使用future而不是手动创建线程:

(defn run-thread-thing []
  (let [f (fn [n s]
            (doseq [i (range n)]
              (prn s i)
              (Thread/sleep (rand 1000))))]
    (future (f 10 "A"))
    (future (f 10 "B")))
  nil)
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下,您将表单传递给future而不是函数.