Java 关闭挂钩未运行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12404712/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Shutdown hook not run
提问by jimkont
I am new to Java/threads and I inherited something like the following code. It is a command line program that main() only starts 5-6 different kind of threads and exits with ^C. I want to add a shutdown hook to close all threads properly and adapted it the following way.
我是 Java/线程的新手,我继承了类似以下代码的内容。这是一个命令行程序,main() 只启动 5-6 个不同类型的线程,并以 ^C 退出。我想添加一个关闭挂钩以正确关闭所有线程并按以下方式对其进行调整。
I added a Shutdown hook and a stopThread() method in all threads (like the one in MyWorker class)
我在所有线程中添加了一个 Shutdown 钩子和一个 stopThread() 方法(就像 MyWorker 类中的那个)
The problem is that when I press ^C I don't see the end message from the Thread's run method. Is this done in the background or is there something wrong with my method. Also, Is there a better pattern I should follow?
问题是,当我按 ^CI 时,看不到 Thread 的 run 方法的结束消息。这是在后台完成的还是我的方法有问题。另外,我应该遵循更好的模式吗?
Thanks
谢谢
public class Main {
public static MyWorker worker1 = new MyWorker();
// .. various other threads here
public static void startThreads() {
worker1.start();
// .. start other threads
}
public static void stopThreads() {
worker1.stopThread();
// .. stop other threads
}
public static void main(String[] args)
throws Exception {
startThreads();
// TODO this needs more work (later)
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
try {
stopThreads();
} catch (Exception exp) {
}
}
});
} }
public class MyWorker extends Thread {
private volatile boolean stop = false;
public void stopThread() {
stop = true;
}
public void run() {
while (!stop) {
// Do stuff here
}
// Print exit message with logger
}
}
回答by Peter Lawrey
When you call System.exit() or terminate via a signal, it stop all the existing threads and starts all the shutdown hooks. i.e. all your threads could be dead by the time you hook starts.
当您调用 System.exit() 或通过信号终止时,它会停止所有现有线程并启动所有关闭挂钩。即,当您挂钩开始时,您的所有线程都可能已死。
Instead of trying to stop threads cleanly, you should ensure resources are closed cleanly.
与其尝试干净地停止线程,不如确保干净地关闭资源。
回答by Nilesh Jadav
Shutdown Hooks may not be executed in some cases!
在某些情况下可能不会执行 Shutdown Hooks!
First thing to keep in mind is that it is not guaranteed that shutdown hooks will always run. If the JVM crashes due to some internal error, then it might crash down without having a chance to execute a single instruction. Also, if the O/S gives a SIGKILL (http://en.wikipedia.org/wiki/SIGKILL) signal (kill -9 in Unix/Linux) or TerminateProcess (Windows), then the application is required to terminate immediately without doing even waiting for any cleanup activities. In addition to the above, it is also possible to terminate the JVM without allowing the shutdown hooks to run by calling Runime.halt() method.
首先要记住的是,不能保证关闭挂钩始终运行。如果 JVM 由于某些内部错误而崩溃,那么它可能会崩溃而没有机会执行单个指令。此外,如果 O/S 发出 SIGKILL ( http://en.wikipedia.org/wiki/SIGKILL) 信号(Unix/Linux 中的 kill -9)或 TerminateProcess (Windows),则应用程序需要立即终止,而不需要甚至等待任何清理活动。除了上述之外,还可以通过调用 Runime.halt() 方法终止 JVM 而不允许关闭挂钩运行。
Shutdown hooks are called when the application terminates normally (when all threads finish, or when System.exit(0) is called). Also, when the JVM is shutting down due to external causes such as user requesting a termination (Ctrl+C), a SIGTERM being issued by O/S (normal kill command, without -9), or when the operating system is shutting down.
当应用程序正常终止时(当所有线程完成时,或当 System.exit(0) 被调用时),将调用关闭钩子。此外,当 JVM 由于外部原因而关闭时,例如用户请求终止 (Ctrl+C)、O/S 发出的 SIGTERM(正常终止命令,没有 -9),或操作系统正在关闭时.
回答by Amit Deshpande
I guess you can shift your code to ExectuterService
我想你可以将你的代码转移到ExectuterService
private final ExecutorService pool;
pool = Executors.newFixedThreadPool(poolSize);
pool.execute(Instance of Runnable);
pool.shutdown();
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
启动有序关闭,其中执行先前提交的任务,但不会接受新任务。如果已经关闭,调用没有额外的效果。
回答by RuntimeException
Try making your threads as daemon threads.
尝试将您的线程设为守护线程。
Add a constructor
添加构造函数
public MyWorker(boolean isDaemon) {
this.setDaemon(true);
}
or set to daemon before calling start.
或在调用 start 之前设置为 daemon。
worker1.setDaemon(true);
worker1.start();
When you press Ctrl C and exit, the threads will be stopped.
当您按 Ctrl C 并退出时,线程将停止。
回答by aymeric
What is happening here is that you invoke the stopThread()
method, but you don't wait the the threads are actually finished before terminating.
这里发生的事情是您调用了该stopThread()
方法,但您不会在终止之前等待线程实际完成。
If you invoke a join()
on all threads before stoping the JVM, you will probably see your 'stop logs'.
如果您join()
在停止 JVM 之前在所有线程上调用 a ,您可能会看到您的“停止日志”。
public static void stopThreads() {
worker1.stopThread();
// .. stop other threads
for(Thread t: workers) {
t.join();
}
}