Scala关机挂钩永远不会运行?

时间:2014-11-15 09:40:43

标签: scala

sys.addShutdownHook的scaladoc说shutdown hooks are NOT guaranteed to be run。现在这是完全合理的,因为如果你向JVM发送一个SIGKILL,或者任何与Windows等价的东西,JVM很难运行关闭挂钩。

但是,sys.addShutdownHook添加的关闭挂钩似乎永远不会运行,尽管那些与Runtime.getRuntime.addShutdownHook一起运行的挂钩。

测试 -

scala> val t = new Thread { override def run = println("hi!") }
t: java.lang.Thread = Thread[Thread-4,5,main]

scala> Runtime.getRuntime.addShutdownHook(t)

scala> hi!
george@george-MacBook:~$ scala

(跳过启动消息)

scala> val t = new Thread { override def run = println("hi!") }
t: java.lang.Thread = Thread[Thread-4,5,main]

scala> sys.addShutdownHook(t.run _)
res0: scala.sys.ShutdownHookThread = Thread[shutdownHook1,5,main]

scala> george@george-MacBook:~$

文档说“钩子是自动注册的:返回的值可以忽略”所以我们不应该添加sys.addShutdownHook返回的线程  (并且无论如何都会导致抛出“IllegalArgumentException:Hook previous registered”)。

另外,调用addShutdownHook返回的线程上运行似乎没有做任何事情,这是可疑的。

1 个答案:

答案 0 :(得分:17)

addShutdownHook的类型签名是(source):

def addShutdownHook(body: => Unit): ShutdownHookThread

因此,很明显为什么您的代码无效。预期是一个名为=> Unit的名字参数,你传递t.run _,它返回() => Unit - 这是完全不同的。

按名称调用参数在执行之前不会运行,将t.run _传递给它意味着在调用call-by-name参数时创建函数 - 您没有通过函数本身而不是call-by-name参数。

使用

sys.addShutdownHook(t.run)

代替。或者根本不使用该线程,只需传递应该执行的代码:

sys.addShutdownHook(println("hi"))