如何为保持运行进程触发java shutdown hook?

时间:2014-11-27 20:50:20

标签: java tomcat process pid shutdown

更新: 现在,为了弄清楚,情况是:有一个项目只能通过调用A类中的main()函数启动,而在main()中添加了一个关闭钩子。 A启动许多其他工作线程,并且它们一直运行直到执行ShutdownHook。 我的问题是如何让关闭挂钩执行?我们曾经使用kill -9 PID来杀死进程。而且我不确定是否会使用直接kill执行shutdown hook。 我搜索了很多,大多数人说杀了-9正确的关机将被忽略?但我的同事说我们一直用这种方式停止服务......我现在完全糊涂了。

public class A {
//...omitted unrelevant
public static void main(String[] args) {
    final A ctrl = new A(configName, routerId);
    ctrl.startup();
    Runtime.getRuntime().addShutdownHook(new Thread() {
    @Override
            public void run() {
                if (logger.isWarnEnabled()) {
                    logger.warn("Kill signal received, starting shutdown...");
                }
                ctrl.shutdown(); //calling the real shutdown
                if (logger.isWarnEnabled()) {
                    logger.warn("Shutdown done, going down.");
                }

                Set<Thread> threadSet=Thread.getAllStackTraces().keySet();
                String currentThreadName = Thread.currentThread().getName();
                for (Thread thread : threadSet) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Killing : " + thread.getName() + " " + thread.getClass().getName());
                    }
                    if (!thread.getName().equals(currentThreadName)) {
                        thread.stop();
                    }
                }
                System.exit(0);
            }
    }
}

// ...

public void shutdown() {
    if (logger.isDebugEnabled()) {
        logger.debug("requesting shutdown");
    }

    for (Worker w : worker) {
        w.requestShutdown();
    }
    for (Thread t : workerThreads) {
        try {
            t.join();
        } catch (InterruptedException e) {
        }
    }
    if (logger.isDebugEnabled()) {
        logger.debug("shutdown finished");
    }

}}

2 个答案:

答案 0 :(得分:1)

按照kiheru的建议使用SIGINT信号。这是按Ctrl + C时发送的内容。

http://en.wikipedia.org/wiki/Unix_signal

答案 1 :(得分:1)

在Linux上,常规kill命令,没有PID以外的参数,是a TERM信号,并将导致关闭钩子执行。

为了演示,请考虑:

import java.util.concurrent.TimeUnit;

public class RunShutdownHook extends Thread {
    public static void main(String... args) {
        System.out.println(Thread.currentThread().getName() + " - Setting the shutdown hook.");
        final Thread nonDaemonThread = new RunShutdownHook();

        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " - Starting shutdown hook.");
                nonDaemonThread.interrupt();

                // Wait to give the interrupted thread a chance to gracefully exit.
                for (int i = 0; i < 10 && nonDaemonThread.isAlive(); i++) {
                    try {
                        TimeUnit.MILLISECONDS.sleep(10);
                    } catch (InterruptedException e) {
                        // We can ignore the InterruptedException because this
                        // thread is about to exit.
                    }
                }
                System.out.println(Thread.currentThread().getName() + " - Finishing shutdown hook.");
            }
        });

        System.out.println(Thread.currentThread().getName() + " - Starting the non-daemon thread.");
        nonDaemonThread.setName("NonDaemonThread");
        nonDaemonThread.start();
        System.out.println(Thread.currentThread().getName() + " - Thread exiting.");
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " - Starting thread.");
        while(!Thread.currentThread().isInterrupted()) {
            System.out.println(Thread.currentThread().getName() + " - Sleeping.");
            try {
                TimeUnit.SECONDS.sleep(1);
                System.out.println(Thread.currentThread().getName() + " - Awakened.");
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() + " - Interrupted.");
                Thread.currentThread().interrupt();
            }
        }
        System.out.println(Thread.currentThread().getName() + " - Thread exiting.");
    }
}

使用Ctrl-C中断:

$ java RunShutdownHook          
main - Setting the shutdown hook.
main - Starting the non-daemon thread.
main - Thread exiting.
NonDaemonThread - Starting thread.
NonDaemonThread - Sleeping.
NonDaemonThread - Awakened.
NonDaemonThread - Sleeping.
^CThread-1 - Starting shutdown hook.
NonDaemonThread - Interrupted.
NonDaemonThread - Thread exiting.
Thread-1 - Finishing shutdown hook.
$ 

从另一个终端运行kill <PID>

$ java RunShutdownHook   
main - Setting the shutdown hook.
main - Starting the non-daemon thread.
main - Thread exiting.
NonDaemonThread - Starting thread.
NonDaemonThread - Sleeping.
NonDaemonThread - Awakened.
NonDaemonThread - Sleeping.
Thread-1 - Starting shutdown hook.
NonDaemonThread - Interrupted.
NonDaemonThread - Thread exiting.
Thread-1 - Finishing shutdown hook.
$ 

从另一个终端运行kill -9 <PID>

$ java RunShutdownHook
main - Setting the shutdown hook.
main - Starting the non-daemon thread.
main - Thread exiting.
NonDaemonThread - Starting thread.
NonDaemonThread - Sleeping.
NonDaemonThread - Awakened.
NonDaemonThread - Sleeping.
zsh: killed     java RunShutdownHook
$