更新: 现在,为了弄清楚,情况是:有一个项目只能通过调用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");
}
}}
答案 0 :(得分:1)
按照kiheru的建议使用SIGINT信号。这是按Ctrl + C时发送的内容。
答案 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
$