Waitgroups in Groovy
Our example demonstrates how to wait for multiple threads to finish using a CountDownLatch
. This is similar to the concept of WaitGroups in other languages.
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors
// This is the function we'll run in every thread.
def worker(int id, CountDownLatch latch) {
println "Worker ${id} starting"
// Sleep to simulate an expensive task.
Thread.sleep(1000)
println "Worker ${id} done"
// Signal that this worker is done
latch.countDown()
}
// Main function
def main() {
// This CountDownLatch is used to wait for all the
// threads launched here to finish.
def numWorkers = 5
def latch = new CountDownLatch(numWorkers)
// Create a fixed thread pool
def executor = Executors.newFixedThreadPool(numWorkers)
// Launch several threads and decrement the CountDownLatch
// counter for each.
(1..numWorkers).each { i ->
executor.execute {
worker(i, latch)
}
}
// Block until the CountDownLatch counter goes back to 0;
// all the workers notified they're done.
latch.await()
// Shutdown the executor
executor.shutdown()
// Note that this approach has no straightforward way
// to propagate errors from workers. For more
// advanced use cases, consider using other concurrency
// utilities provided by Java/Groovy.
}
// Run the main function
main()
To run the program, save it as waitgroups.groovy
and use the groovy
command:
$ groovy waitgroups.groovy
Worker 1 starting
Worker 2 starting
Worker 3 starting
Worker 4 starting
Worker 5 starting
Worker 1 done
Worker 2 done
Worker 3 done
Worker 4 done
Worker 5 done
The order of workers starting up and finishing is likely to be different for each invocation.
In this Groovy example, we’ve used a CountDownLatch
to replicate the functionality of a WaitGroup. The CountDownLatch
is initialized with the number of workers, and each worker calls countDown()
when it’s finished. The main thread waits for all workers to finish by calling await()
on the latch.
We’ve also used a FixedThreadPool
to manage our threads, which is a common practice in Java/Groovy for handling multiple concurrent tasks.
Remember that while this example demonstrates basic concurrency, Groovy and Java offer more advanced concurrency utilities for complex scenarios.