启动 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 的一个参数. 因此同名肯定是不能支持的.