Timers in Mercury

We often want to execute Java code at some point in the future, or repeatedly at some interval. Java’s ScheduledExecutorService makes both of these tasks easy. We’ll look at using this for scheduling tasks.

import java.util.concurrent.*;
import java.time.Instant;

public class Timers {
    public static void main(String[] args) throws InterruptedException {
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        // This timer will wait 2 seconds.
        ScheduledFuture<?> timer1 = scheduler.schedule(() -> {
            System.out.println("Timer 1 fired");
        }, 2, TimeUnit.SECONDS);

        // Block until the timer fires
        timer1.get();

        // If you just wanted to wait, you could have used
        // Thread.sleep(). One reason a timer may be useful is
        // that you can cancel the timer before it fires.
        // Here's an example of that.
        ScheduledFuture<?> timer2 = scheduler.schedule(() -> {
            System.out.println("Timer 2 fired");
        }, 1, TimeUnit.SECONDS);

        boolean cancelled = timer2.cancel(false);
        if (cancelled) {
            System.out.println("Timer 2 stopped");
        }

        // Give timer2 enough time to fire, if it ever
        // was going to, to show it is in fact stopped.
        Thread.sleep(2000);

        scheduler.shutdown();
    }
}

The first timer will fire ~2s after we start the program, but the second should be stopped before it has a chance to fire.

$ javac Timers.java
$ java Timers
Timer 1 fired
Timer 2 stopped

In this Java version:

  1. We use ScheduledExecutorService instead of Go’s timer.
  2. scheduler.schedule() is used to create tasks that run after a delay.
  3. We use ScheduledFuture to represent the pending completion of the scheduled task.
  4. timer1.get() blocks until the timer fires, similar to <-timer1.C in Go.
  5. timer2.cancel(false) is used to stop the timer, equivalent to timer2.Stop() in Go.
  6. We use Thread.sleep() instead of time.Sleep().

The structure and behavior of the program remain similar to the original, demonstrating the concepts of scheduling tasks and cancelling them before they execute.