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返回的线程上运行似乎没有做任何事情,这是可疑的。
答案 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"))