启动 Scala 工程, 我们有时候可能需要做这样的处理: 获取打断(Interrupt )信号, 在程序关闭前做最后一些操作.

在 C 中, 我们一般可以用 signal 来实现, 而在 scala 中,我们同样有类似的机制.

我们使用的原型是

package scala
package object sys extends scala.AnyRef {
  def addShutdownHook(body : => scala.Unit) : scala.sys.ShutdownHookThread = 
    { /* compiled code */ }
}

我做了一个简单的 object 来管理它:

import scala.collection.mutable.{Map => MMap}

object SystemShutdownHookRegister {
  lazy val hooks = MMap[String, (() => Unit)]()
  val activate: Boolean = sys.addShutdownHook(
    SystemShutdownHookRegister.doShutdown()).isAlive

  /**
    * @param name name of the function
    * @param exec registed function
    * @return true for a new one , and false for replaced another
    */
  def register(name: String, exec: () => Unit): Boolean =
    hooks.synchronized(hooks.put(name, exec).isEmpty)

  /**
    * @param name deregisted name
    * @return true for some function removed
    */
  def deregister(name: String): Boolean =
    hooks.synchronized(hooks.remove(name).isDefined)

  def doShutdown(): Unit =
    hooks.synchronized(hooks.foreach(_._2()))
}

调用也很简单

SystemShutdownHookRegister.register(
  "hello",
  () => (println("my-hello")))

注册名为"hello", 若这时候打断, 也就是程序被 ctrl + C 了, 那么系统会自动运行 println("my-hello")

有时候我们发现其实这个并不需要了, 我们还可以反注册它

SystemShutdownHookRegister.deregister("hello")

注意, 本质上, 它其实就是一个 mutable 的 Map, key 是注册名, value 是类型为 () => Unit 的一个参数. 因此同名肯定是不能支持的.

Categories: Code

Yu

Ideals are like the stars: we never reach them, but like the mariners of the sea, we chart our course by them.

Leave a Reply

Your email address will not be published.