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