Say you've got a method that you're going to run as a thread:

def functionAsThread[F](function: => F, name: Option[String] = None) = { val t = new Thread( new Runnable() { def run() { function } } ) t.start() name.foreach(t.setName) t } def periodicallyDoSomething(): Unit = { while(keepDoingIt_?) { doSomething() Thread.sleep(frequency) } } val somethingDoer = functionAsThread(periodicallyDoSomething, Some("SomethingDoer"))

When inevitably the thread must stop, such as in a clean shutdown, you will of course tell somethingDoer to halt with somethingDoer.interrupt() .

How should you handle the potential InterruptedException thrown by Thread.sleep ?

Your Scala brain should lead you to wrap function in a Try and pass in a PartialFunction for recovery, like so:

def functionAsThread[F](function: => F, name: Option[String] = None, recoverWith: PartialFunction[Throwable, Unit]) = { val t = new Thread( new Runnable() { def run() { Try(function).recover(recoverWith) } } ) t.start() name.foreach(t.setName) t }

You'll be as frustrated as I was when this doesn't work. The exception will still be uncaught!

Digging into Try a bit more, we see why this doesn't work:

object Try { def apply[T](r: => T): Try[T] = try Success(r) catch { case NonFatal(e) => Failure(e) } }

That's interesting. Try is just a try{}catch{} that returns a convenient Success or Failure object. What's this NonFatal business, though?

object NonFatal { def apply(t: Throwable): Boolean = t match { // VirtualMachineError includes OutOfMemoryError and other fatal errors case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError | _: ControlThrowable => false case _ => true } def unapply(t: Throwable): Option[Throwable] = if (apply(t)) Some(t) else None

Scala considers InterruptedException to be a fatal exception. That is, there is a deliberate design decision that an implementor must use try{}catch{} to handle it. This makes sense because a thread that is sleeping should explicitly be told what to do if it is interrupted. That's just a part of using Thread.sleep .

So, a way to correct the method is:

def periodicallyDoSomething(): Unit = { try { while(keepDoingIt_?) { doSomething() Thread.sleep(frequency) } } catch { case e: InterruptedException => handleInterruption() }