addShutdownHook 和 setUncaughtExceptionHandler 在 java 中无法按预期工作

发布于 2024-08-23 05:42:22 字数 1587 浏览 7 评论 0原文

我有一个多线程程序,其中一个线程可以监视多个线程。功能设计如下:

主程序进行初始化并启动观察者线程,在 void Main() 中,我有一行

Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownThread(), "Exit Listener"));

当我不启动观察者线程时,当我终止程序时调用 ShutdownThread,但是当我启动时Watcher 线程中有一个死循环,未调用 ShutdownThread (我在该线程中打印出一条消息)。这非常非常奇怪。有什么解释吗?

观察者线程是这样的:

public void run(){
   boolean running=false;
   thread a=new thread(...); //Do the same thing for b, c, d...
   while(true){
   if (a.isActive()){
     if (running)
        thread a= new thread(...);
     a.start();
     running=true;
   }
   Thread.sleep(1000); //try catch block...
}

我想要的是一个优雅的关闭,在收到终止信号后,shutdownThread 运行,设置一个标志并中断所有线程,并等待线程中断它,或者超时,以便剩余的线程线程可以被杀死。所有线程都可以捕获中断,并检查是否设置了标志,如果设置了,它将中断 shutdownThread,然后自行退出。相反,我看到的是所有线程都自行终止,根本不进行任何清理。

使用信号怎么样?有没有好的跨平台代码?

然后,setUncaughtExceptionHandler 也不起作用。我做了测试,发现处理程序根本没有被调用。我不知道为什么。处理程序的代码是:

    public static class ErrHandler implements Thread.UncaughtExceptionHandler{
    public final void uncaughtException(Thread t, Throwable e) {
            Error(t + "died, threw exception: " + e);
        }
    }//this is in public class globals

使用 Is 挂钩它

producer.setUncaughtExceptionHandler(Globals.errhandler);

我在代码中 ,并且我只看到原始的 e.printStack()。看来我无法覆盖它,无论是在父线程中还是在其本身中。这太令人沮丧了。我正在考虑将一个条目放入队列中,然后在其他地方读取它。至少这可能有效。

哦,整个目的是确保如果任何线程由于运行时异常而死亡,观察者线程将检查异常是否足够致命,并决定重新启动该线程或完全退出。同时,我希望程序在用户结束时优雅地结束(一个中断被发送到保护程序线程,以便它转储结果,然后中断回来告诉我们已经准备好退出)。

I have a multi-threaded program, where I have one thread to watch over several threads. The functioning is designed like this:

Main program does initiation and starts Watcher Thread, in void Main(), I have the line

Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownThread(), "Exit Listener"));

When I don't start the watcher thread, the ShutdownThread is called when I terminate the program, but when I start the Watcher thread which has a dead loop in it, the ShutdownThread is not called (I print out a message in that thread). That is very very strange. Any explanations?

The watcher thread is like:

public void run(){
   boolean running=false;
   thread a=new thread(...); //Do the same thing for b, c, d...
   while(true){
   if (a.isActive()){
     if (running)
        thread a= new thread(...);
     a.start();
     running=true;
   }
   Thread.sleep(1000); //try catch block...
}

What I would like is a graceful shutdown, that upon getting a terminate signal, shutdownThread is run, sets a flag and interrupts all threads, and waits for the threads to interrupt it, or it timeout so that the remaining threads can be killed. All the threads can catch an interuption, and check if a flag is set, if set, it will interrupt shutdownThread and then exit itself. Instead what I am seeing is all the threads are terminating by itself, doing no cleanup at all.

How about using signals? Is there any good cross-platform code for that?

Then, setUncaughtExceptionHandler doesn't work either. I did testing, and found that the handler isn't called at all. I don't know why. The code for the handler is:

    public static class ErrHandler implements Thread.UncaughtExceptionHandler{
    public final void uncaughtException(Thread t, Throwable e) {
            Error(t + "died, threw exception: " + e);
        }
    }//this is in public class globals

I hook it using

producer.setUncaughtExceptionHandler(Globals.errhandler);

Is in my code, and I only see the original e.printStack() instead. It seems that I can't override it, either in the parent thread, or in itself. This is so frustrating. I'm thinking of putting a Entry into a queue, and reading it elsewhere. At least that may work.

Oh, the whole purpose is to make sure that if any of the threads die because of runtime exceptions, the watcher thread will check whether the exception is fatal enough, and decide to restart that thread or to quit altogether. At the same time, I would like the program to end gracefully (an interrupt is sent to saver threads so that it dumps the results out, and then interrupts back to tell that we are ready to quit) when the user ends it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

落花随流水 2024-08-30 05:42:22

不知道它是否对您有帮助,但我们遇到了同样的行为。
并非所有异常都会正确路由到已注册的 ExceptionHandler。

我想知道并发框架是否存在单元测试。因为必须检测到这一点。

我们自己实现了 ScheduledExecutorService,使用 ScheduledExecutorService 实例作为委托,并将每个方法的参数 Runnable/Callable 封装在 Runnable/Callable 实现中,以纠正行为。

Dunno if it helps you, but we encountered the same behaviour.
Not all exceptions are routed correctly to the registered ExceptionHandler.

I wonder if Unit-Tests exists at all for the concurrent framework. Because this had to be detected.

We implemented the ScheduledExecutorService by ourself by using a ScheduledExecutorService instance as delegate and encapsulate the parameter Runnable/Callable of each method in a Runnable/Callable implementation which corrects the behaviour.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文