Timeouts in Karel

Timeouts are important for programs that connect to external resources or that otherwise need to bound execution time. Implementing timeouts in Java is possible using the ExecutorService and Future classes.

import java.util.concurrent.*;

public class Timeouts {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        // For our example, suppose we're executing an external
        // call that returns its result after 2s.
        Future<String> future1 = executor.submit(() -> {
            Thread.sleep(2000);
            return "result 1";
        });

        try {
            // Here we're implementing a timeout.
            // We'll wait for the result for 1 second.
            String result = future1.get(1, TimeUnit.SECONDS);
            System.out.println(result);
        } catch (TimeoutException e) {
            System.out.println("timeout 1");
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

        // If we allow a longer timeout of 3s, then we'll get the result.
        Future<String> future2 = executor.submit(() -> {
            Thread.sleep(2000);
            return "result 2";
        });

        try {
            String result = future2.get(3, TimeUnit.SECONDS);
            System.out.println(result);
        } catch (TimeoutException e) {
            System.out.println("timeout 2");
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

        executor.shutdown();
    }
}

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

$ javac Timeouts.java
$ java Timeouts
timeout 1
result 2

In this Java version:

  1. We use ExecutorService to manage our asynchronous tasks.
  2. Each task is submitted to the executor, which returns a Future.
  3. We use future.get(timeout, unit) to wait for the result with a timeout.
  4. If the timeout is exceeded, a TimeoutException is thrown.

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