Timers in Miranda

We often want to execute code at some point in the future, or repeatedly at some interval. Java’s Timer and ScheduledExecutorService features make both of these tasks easy. We’ll look first at timers and then at scheduled tasks.

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Timers {
    public static void main(String[] args) throws InterruptedException {
        // Timers represent a single event in the future. You
        // tell the timer how long you want to wait, and it
        // will execute a task at that time. This timer will wait 2 seconds.
        Timer timer1 = new Timer();
        timer1.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("Timer 1 fired");
            }
        }, 2000);

        // We use Thread.sleep to wait for the timer to complete
        Thread.sleep(2000);

        // 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.
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        Runnable task = () -> System.out.println("Timer 2 fired");
        var future = executor.schedule(task, 1, TimeUnit.SECONDS);

        // Cancel the timer before it fires
        boolean cancelled = future.cancel(false);
        if (cancelled) {
            System.out.println("Timer 2 stopped");
        }

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

        // Shutdown the executor
        executor.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, we use java.util.Timer for the first timer and ScheduledExecutorService for the second timer. The ScheduledExecutorService provides more flexibility and is generally preferred in modern Java applications for scheduling tasks.

The Thread.sleep() calls are used to simulate waiting for the timers, similar to the time.Sleep() function in the original example.

Instead of channels, we use the TimerTask and Runnable interfaces to define the actions to be performed when the timers fire.

The cancel() method on the ScheduledFuture returned by schedule() is used to stop the second timer, analogous to the Stop() method in the original example.