Timeouts in Groovy

Timeouts are important for programs that connect to external resources or that otherwise need to bound execution time. Implementing timeouts in Groovy is straightforward using threads and the CountDownLatch class.

import java.util.concurrent.*

// For our example, suppose we're executing an external
// call that returns its result after 2 seconds.
def executeWithDelay(Closure closure, long delayMillis) {
    Thread.start {
        Thread.sleep(delayMillis)
        closure.call()
    }
}

def main() {
    def latch1 = new CountDownLatch(1)
    def result1 = null

    executeWithDelay({
        result1 = "result 1"
        latch1.countDown()
    }, 2000)

    // Here we implement a timeout using CountDownLatch.
    // We'll wait for the result for 1 second.
    if (latch1.await(1, TimeUnit.SECONDS)) {
        println result1
    } else {
        println "timeout 1"
    }

    // If we allow a longer timeout of 3 seconds, then the operation
    // will succeed and we'll print the result.
    def latch2 = new CountDownLatch(1)
    def result2 = null

    executeWithDelay({
        result2 = "result 2"
        latch2.countDown()
    }, 2000)

    if (latch2.await(3, TimeUnit.SECONDS)) {
        println result2
    } else {
        println "timeout 2"
    }
}

main()

Running this program shows the first operation timing out and the second succeeding.

$ groovy timeouts.groovy
timeout 1
result 2

In this Groovy example, we use threads to simulate asynchronous operations and CountDownLatch to implement timeouts. The executeWithDelay function simulates an operation that takes some time to complete.

We use CountDownLatch.await() with a timeout to wait for the result. If the latch counts down before the timeout, we receive and print the result. Otherwise, we print a timeout message.

This approach provides similar functionality to the original example, allowing us to bound the execution time of operations in Groovy.