gpt4 book ai didi

windows - 强制关闭时的scala关闭钩子(Hook)

转载 作者:行者123 更新时间:2023-12-03 11:13:35 24 4
gpt4 key购买 nike

我的 scala 程序中有关闭钩子(Hook),当使用 ctrl+c 退出时它工作正常,但是在用户刚刚退出命令行窗口后是否有某种方法仍然可以执行某些操作,因为关闭不是以这种方式调用的?

最佳答案

我很难想象无论如何你都可以保证资源被清理干净。您的应用程序终止的原因有很多:定期终止,异常终止,用户停止进程,您的机器死机,......

但是,您可以构建各种安全网:正如您所做的那样,可以定义一个关闭处理程序来在您的应用程序停止时清理资源。现在,如果您想确保清理某些资源,即使整个进程停止运行,您也可以创建第二个进程,其唯一目的是检查您的应用程序是否仍在运行,如果没有,清理资源。

现在这需要两个进程至少进行最少的通信:一个进程需要知道另一个进程是否仍在运行。

有多种沟通方式。根据您希望设计的复杂程度,有些更适合。我可以想到以下几种沟通方式:

  • 让一个进程构建您的应用程序。这个进程会是对方的父进程,可以检查对方是否还在运行
  • 让进程使用远程过程调用 (RMI) 进行通信。您可以使用 ping 方法定义接口(interface)返回 pong ,允许一个进程检查另一个进程是否还活着。
  • 在比 RMI 更低的级别上,使用套接字进行类似的通信。
  • 进程可以通过文件系统进行通信,即一个进程通过写入文件来 ping 另一个进程,如果另一个进程没有对协议(protocol)使用react,则该进程清理资源。这可能不如前一种方法可靠,而且可能也更慢,尽管我没有数据支持我的直觉。

  • 我不是专家,所以肯定有很多选择。

    你可以尝试做这样的事情:
    package application

    import java.io._
    import java.nio.file._
    import java.nio.file.attribute.BasicFileAttributes

    object Bootstrap {
    def main(args: Array[String]): Unit = {
    val workingDirectory = Files.createTempDirectory("newTemp")
    println("Working Directory: " + workingDirectory)
    val processBuilder = new ProcessBuilder("java", "-jar", "/path/to/process.jar", workingDirectory.toAbsolutePath.toString)
    processBuilder.directory(workingDirectory.toFile)
    val process = processBuilder.start()
    new StreamGobbler(process.getErrorStream, "ERROR").start()
    new StreamGobbler(process.getInputStream, "OUTPUT").start()
    process.waitFor()
    println("Process stopped working")
    cleanup(workingDirectory)
    }

    def cleanup(workingDirectory: Path): Unit = {
    Files.walkFileTree(workingDirectory, new SimpleFileVisitor[Path]{
    override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = {
    Files.deleteIfExists(file)
    super.visitFile(file, attrs)
    }

    override def postVisitDirectory(dir: Path, exc: IOException): FileVisitResult = {
    Files.deleteIfExists(dir)
    super.postVisitDirectory(dir, exc)
    }
    })
    }
    }

    class StreamGobbler(is: InputStream, `type`: String) extends Thread {

    override def run(): Unit = {
    val isr = new InputStreamReader(is)
    val br = new BufferedReader(isr)
    var line = br.readLine()
    while (line != null){
    System.out.println(`type` + "> " + line)
    line = br.readLine()
    }
    }
    }

    object Process {
    def main(args: Array[String]): Unit = {
    val workingDirectory = Paths.get(args(0))
    Files.createTempFile(workingDirectory, "Resource", ".txt")
    for(i <- 1 to 8) {
    println("Process is running")
    Thread.sleep(1000)
    }
    println("Suppose the process got killed here")
    }
    }

    要运行它,使用 Process 创建一个可执行 jar作为入口点,更新 "path/to/process.jar"并运行 Bootstrap .即使您终止调用的子进程,仍应清理资源。

    我拿了 StreamGobbler来自 ProcessBuilder: Forwarding stdout and stderr of started processes without blocking the main thread ,仅将其从 Java 转换为 Scala。

    请再次注意,如果您的 Bootstrap进程被杀死,那么您的资源将不会被清理。根据清理完成的重要性,您可以
  • 创建多个独立的清理进程,在没有主进程的情况下运行(即,让父进程只创建多个清理进程,它们进行通信(例如,通过 RMI)以独立于父进程是否仍在运行来协调清理)
  • 在通过网络通信的不同机器上创建多个独立的清理进程。即使发生本地停电事件,这也可以让您进行清理。

  • 请记住,为了将应用程序无法正确清理的风险降至最低,清理工作将变得更加复杂。可能还有现有的解决方案(也许应用程序服务器会为您做类似的事情?),但现有的解决方案可能会反过来强制您依赖您不想要的。

    关于windows - 强制关闭时的scala关闭钩子(Hook),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26314355/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com