【问题标题】:Hazelcast prevents the JVM from terminatingHazelcast 防止 JVM 终止
【发布时间】:2013-09-09 15:30:14
【问题描述】:

我们在旧版 Java 集群应用程序中使用 Hazelcast 2.6.2。当应用程序停止时,JVM 不再终止。似乎是由于 Hazelcast 线程没有被标记为守护进程。我没有找到通过 Hazelcast API 标记它们的方法。

有没有推荐的解决方案来防止 Hazelcast 阻止 JVM 终止?

问候

【问题讨论】:

  • “应用程序停止时”:如何?您是简单地结束所有非守护线程还是实际使用System.exit()?后者应该始终工作,无论是否有任何守护线程正在运行。
  • 你在打电话给hazelcast.shutdownAll();吗?
  • @JoachimSauer:所有非守护线程都简单地结束,否则一个简单的 System.exit() 就足以像你说的那样终止 JVM
  • @Gray: 不幸的是我不知道应用程序何时结束,没有回调让我执行 hazelcast.shutdownAll() 甚至 System.exit()
  • 我添加了一个答案,说明如何使用关闭挂钩。

标签: java multithreading jvm hazelcast


【解决方案1】:

查看Hazelcast Javadocs,看到有shutdownAll();方法。引用 javadocs:

关闭此 JVM 上所有正在运行的 Hazelcast 实例,包括正在运行的默认实例。它不会关闭集群的所有成员,而只会关闭在此 JVM 上运行的成员。

如果你不关闭它,我怀疑那里有没有被终止的非守护线程会阻止 JVM 关闭。

【讨论】:

  • 我认为这行不通。由于 JVM 不会终止,因此关闭挂钩将永远不会执行。 :'(
  • 我认为 hazelcast.shutdownAll() 将允许 JVM 终止(当应用程序线程当然结束时),因此会触发关闭挂钩。不是相反。
  • 呃。你是对的@Tom。恐怕您将不得不在应用程序退出时以某种方式触发对shutdownAll() 的调用。
  • 正确的方法。您需要以某种方式检测您的应用程序正在关闭。如果您使用的是框架,请寻找合适的关闭挂钩并致电 Hazelcast shutdownAll()
【解决方案2】:

在 Tomcat 中,我通过 server.xml 添加了一个生命周期监听器。

<Listener className="com.mycompany.StartupHandler" DEBUG="false"/>

我的 StartupHandler.class 放在 $TOMCAT_HOME/lib/ 的一个 jar 中,它包含这个 sn-p 以在检测到 Tomcat 关闭时触发 Hazelcast 关闭:

public void lifecycleEvent(LifecycleEvent lifecycleEvent) {
    String eventType = lifecycleEvent.getType();
    if (eventType.equals(Lifecycle.BEFORE_STOP_EVENT)) {
        com.hazelcast.core.Hazelcast.shutdownAll();
    }
}

其他网络服务器应该有类似的关闭钩子,您可以在其中自动调用 Hazelcast.shutdownAll()。

请参阅 https://github.com/hazelcast/hazelcast/issues/718 了解我在同一主题上的原始 Hazelcast 线程。感谢这里提示调用 Hazelcast.shutdownAll()。这个想法结合我的 Tomcat 关闭钩子应该足以为我解决这个问题,希望你也觉得它有用。

【讨论】:

  • 感谢您提出这个有趣的想法。不幸的是,它在这里不适用,因为我们不使用 Tomcat。我们需要一个便携的解决方案。
【解决方案3】:

这是一种独立于 Tomcat 的方法来检测 JVM 关闭。它使用非守护线程轮询守护线程以检测 JVM 何时关闭(JVM 自动关闭守护线程)。轮询代码中的静态 IS_SHUTDOWN 标志,或在此处内联对 Hazelcast.shutdownAll() 的调用。小心竞争条件,因为如果您尝试在 Hazelcast 启动之前关闭它,那么它会在您的日志中引发异常。该异常不会破坏任何东西,但看起来很难看。

/**
 * Non-Daemon thread monitors a sacrificial, low-priority, daemon thread
 * to detect when JVM is shutting down, so shutdown hooks can be invoked.
 * @author justin.cranford
 */
public class ThreadUtil {
    public static boolean IS_SHUTDOWN = false;  // threads can poll this flag, or inline below where flag is set
    private static final Thread DAEMON_THREAD = new Thread() {
        public void run() {
            while (true) {
                try {
                    Thread.sleep(Long.MAX_VALUE);   // sleep forever
                } catch(Exception e) {}
            }
        }
    };
    private static final Thread NONDAEMON_THREAD = new Thread() {
        public void run() {
            while (true) {
                if (!DAEMON_THREAD.isAlive()) { // poll forever, until daemon thread dies
                    ThreadUtil.IS_SHUTDOWN = true;
                    return;
                }
                try {
                    Thread.sleep(1000); // poll every 1000msec = 1sec
                } catch(Exception e) {}
            }
        }
    };
    static {
        DAEMON_THREAD.setName("ShutdownMonitorNonDaemonThread");
        DAEMON_THREAD.setPriority(Thread.MIN_PRIORITY);
        DAEMON_THREAD.setDaemon(true);
        DAEMON_THREAD.start();
        try {
            Thread.sleep(3000); // wait 3000msec = 3sec before monitoring
        } catch(Exception e) {}
        NONDAEMON_THREAD.setName("ShutdownMonitorDaemonThread");
        NONDAEMON_THREAD.setPriority(Thread.MIN_PRIORITY);
        NONDAEMON_THREAD.setDaemon(false);
        NONDAEMON_THREAD.start();
    }
}

【讨论】:

  • 我认为这也行不通。你使用的非守护线程会阻止JVM终止(根据geekexplains.blogspot.fr/2008/06/…),所以守护线程永远不会停止,所以我们不会检测到“关闭”。
【解决方案4】:

正如大家所说,hazelcastInstance.shutdownAll() 是解决方案。

但是,我想在 Hazelcast 中获得一个新功能——同时提供一个恶魔客户端。有很多用例需要在应用程序结束后立即关闭缓存实例。

【讨论】:

    猜你喜欢
    • 2011-07-29
    • 1970-01-01
    • 2019-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    相关资源
    最近更新 更多