Timers in Scala

import scala.concurrent.{Future, ExecutionContext}
import scala.concurrent.duration._
import scala.util.{Success, Failure}

object Timers {
  def main(args: Array[String]): Unit = {
    implicit val ec: ExecutionContext = ExecutionContext.global

    // Timers represent a single event in the future. In Scala, we can use
    // `Future` with `DelayedFuture` to achieve a similar effect. This timer
    // will wait 2 seconds.
    val timer1 = akka.pattern.after(2.seconds, using = ec) {
      Future.successful(())
    }

    // We block on the future until it completes, indicating that the timer fired.
    timer1.onComplete {
      case Success(_) => println("Timer 1 fired")
      case Failure(e) => println(s"Timer 1 failed: ${e.getMessage}")
    }

    // If you just wanted to wait, you could have used `Thread.sleep`.
    // One reason a timer may be useful is that you can cancel it before it fires.
    // Here's an example of that using `Promise`.
    val promise = scala.concurrent.Promise[Unit]()
    val timer2 = promise.future

    Future {
      Thread.sleep(1000)
      promise.trySuccess(())
    }

    val stop2 = promise.tryFailure(new InterruptedException("Timer cancelled"))
    if (stop2) {
      println("Timer 2 stopped")
    }

    // Give the `timer2` enough time to complete, if it ever was going to,
    // to show it is in fact stopped.
    Thread.sleep(2000)
  }
}

To run this Scala program:

$ scala Timers.scala
Timer 1 fired
Timer 2 stopped

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

In this Scala version:

  1. We use Future and Promise to simulate timers.
  2. The akka.pattern.after method is used to create a delayed future, similar to Go’s time.NewTimer.
  3. Instead of channels, we use Future and its callbacks to handle timer completion.
  4. The Promise allows us to manually complete or fail a future, which we use to simulate stopping a timer.
  5. We use Thread.sleep instead of time.Sleep for simple delays.

Note that this Scala version requires the Akka library for the after method. In a real Scala project, you would typically use a build tool like SBT and include Akka as a dependency.