强制 JVM 在终止之前完成代码块

Posted

技术标签:

【中文标题】强制 JVM 在终止之前完成代码块【英文标题】:Force JVM to finish code block before terminate 【发布时间】:2014-01-27 17:02:10 【问题描述】:

我有以下代码:

public class LogWriter implements Runnable 
private static BlockingQueue<LogRecord> logQueue;

static 
    logQueue = new ArrayBlockingQueue<LogRecord>(30);


@Override
public void run() 
    Integer errorNo = 0;
    configureLogger();

    while (true) 
        try 
            LogRecord record = logQueue.take();
            consumeLogRecord(record);
            System.out.println(++errorNo + " - Logged error in file '" + LoggerConfig.LOG_PATH + "'");
            record = null;
         catch (InterruptedException e) 
            System.out.println(e.getMessage());
        
    


这是用 Java 编写的 LibreOffice 插件记录器的一部分。当 LibreOffice 关闭时,它会简单地杀死它的插件(到目前为止,我还不确定),但在向它们发送它正在关闭的信号之前,我可以在我的代码中检测到它(通过 UNO API) .在收到来自 LibreOffice 的终止信号后,我想将我的 LogRecord 队列刷新到日志文件并将 while(true) 更改为 false,以便方法 run() 可以适当地完成,释放它拥有的资源。所以我的问题是,我如何告诉 JVM 等待这个操作是高优先级的,它不应该在完成之前终止?

【问题讨论】:

***.com/questions/5747803/… 关闭钩子是最好的方法 - 你不能强制它们一直工作,但总的来说,它们是你完成这项工作的最佳工具. 如果您知道如何检测代码中的关机信号...究竟是什么问题? 问题是即使 LibreOffice 说它正在关闭,它也不会等待代码来做一些事情,比如关闭文件、释放资源......这就是为什么我问是否在这段代码完成之前,有一种方法可以让 JVM 保持活动状态。 【参考方案1】:

关于关闭挂钩的建议必须谨慎对待。关闭挂钩是不得已的设备,您可以在其中尝试通过任何其他方式挽救您无法实现的功能。您不能依赖任何正常的假设,例如 System.out 仍然打开,您的日志文件仍然打开,甚至文件系统可用,等等。

关闭挂钩的一个用例是尝试正常关闭获取的资源,而不尝试进一步的数据传输。

应该采取的方法是:

    告诉自己 LibreOffice 给你的确切条款:你是否有特定的超时时间来完成你的工作?

    尽量减少任何时间点的待处理工作,从而最大限度地提高在超时时间内完成工作的机会。

【讨论】:

谢谢,关闭钩子是一个很好的提示,我添加了它作为你所说的最后手段,但是在关闭过程的正确流程中,现在的解决方案是 Java 捕获来自 LibreOffice 的关闭信号, 不允许再向队列中添加任何日志并刷新记录器,从而完成插件。【参考方案2】:

你可以使用。

Runtime.getRuntime().addShutdownHook(Thread);

关闭挂钩将是最好的选择。

【讨论】:

以上是关于强制 JVM 在终止之前完成代码块的主要内容,如果未能解决你的问题,请参考以下文章

静态块 static

对之前的所有的代码进行总结

对之前的所有的代码进行总结

静态代码块非静态代码块(普通代码块)和构造方法的执行顺序

static{}(静态代码块)与{}(非静态代码块)的异同点(转自 べ袽猓柯苡づ)

jQuery:强制执行 document.ready() 调用的顺序