Title here
Summary here
Our example demonstrates how to wait for multiple concurrent operations to finish using a CountDownLatch in Clojure.
(ns waitgroups-example.core
(:require [clojure.core.async :refer [go]]
[clojure.java.io :as io])
(:import (java.util.concurrent CountDownLatch)))
;; This is the function we'll run in every thread.
(defn worker [id]
(println (format "Worker %d starting" id))
;; Sleep to simulate an expensive task.
(Thread/sleep 1000)
(println (format "Worker %d done" id)))
(defn -main []
;; This CountDownLatch is used to wait for all the
;; threads launched here to finish.
(let [latch (CountDownLatch. 5)]
;; Launch several threads and decrement the CountDownLatch
;; counter for each.
(dotimes [i 5]
;; Wrap the worker call in a future that makes sure to tell
;; the CountDownLatch that this worker is done. This way the worker
;; itself does not have to be aware of the concurrency primitives
;; involved in its execution.
(go
(try
(worker (inc i))
(finally
(.countDown latch)))))
;; Block until the CountDownLatch counter goes back to 0;
;; all the workers notified they're done.
(.await latch)
;; Note that this approach has no straightforward way
;; to propagate errors from workers. For more
;; advanced use cases, consider using core.async's error handling capabilities.
))
(comment
(-main)
)
To run the program:
$ lein run
Worker 1 starting
Worker 5 starting
Worker 4 starting
Worker 3 starting
Worker 2 starting
Worker 4 done
Worker 1 done
Worker 2 done
Worker 5 done
Worker 3 done
The order of workers starting up and finishing is likely to be different for each invocation.
In this Clojure version:
clojure.core.async/go
to create lightweight threads (similar to goroutines).CountDownLatch
, which serves a similar purpose.dotimes
to launch multiple workers, each in its own go
block.latch
is countdown in a finally
block to ensure it happens even if an exception occurs..await
on the latch to wait for all workers to complete, similar to WaitGroup.Wait()
.This example demonstrates concurrent programming in Clojure, showing how to manage multiple concurrent operations and wait for their completion.