Reputation: 149
I've written a standalone uberjar with a main method that spins off two go blocks like so:
(defn -main [& args]
(let [c (chan)]
(go (while true
(>! c (rand))))
(go (while true
(<! c)))))
But when I execute the program it quickly terminates. Why? My intention is to have the go blocks execute indefinitely. I ended up sticking
(<!! (chan))
at the end of the main function to prevent termination. Is there a better way to do that?
Upvotes: 1
Views: 296
Reputation: 3378
The program terminates because, after those go
blocks are created, the main function is finished. With nothing to do, it exits; that shouldn't be much of a surprise. Of course, we'd prefer the main application keep running while all of those go
blocks are still alive.
Each of those go
blocks produces a channel; you could wait until one of them returns something (though as it stands, they never will). Try blocking with alts!!
while they spin:
(defn -main
[& args]
(let [c (chan)]
(alts!!
[(go (while true
(>! c (rand))))
(go (while true
(<! c)))])))
So, your main thread will block until one of the channels in alts!!
returns a value. Right now, it'll block forever, but this structure sets you up for more interesting things. For example, you could exit the application when the random value is above some threshold:
(defn -main
[& args]
(let [c (chan)]
(alts!!
[(go (while true
(>! c (rand))))
(go-loop [value (<! c)]
(if (> value 0.8)
value ; return value from the go block
(recur (<! c))))])))
Or, go wild, timeout after a second:
(defn -main
[& args]
(let [c (chan)]
(alts!!
[(go (while true
(>! c (rand))))
(go (while true
(<! c)))
(timeout 1000)])))
The larger takeaway is that there's a good chance you're going to want to block your main thread to wait for those asynchronous go
blocks to finish up their business.
Upvotes: 1