【问题标题】:How to gain a lost connection to server without restarting the Server, when a listener thread dies当侦听器线程死亡时,如何在不重新启动服务器的情况下获得与服务器的丢失连接
【发布时间】:2012-04-08 18:10:08
【问题描述】:

我正在尝试通过轮询来收听 RabbitMQ 队列。但是由于网络问题,如果一旦与队列的连接丢失,那么线程就会默默地关闭并且连接和一切都关闭。但这是一个后台任务,我们不会知道直到队列真的变大并开始发送通知。

请有人帮助我优雅地关闭线程(我想我已经通过仔细处理 catch 子句中的异常来做到这一点)。但我不知道如何重新启动已停止的线程。

有没有办法可以重新启动已停止线程的新实例。

PS:我正在使用 @postconstruct 实例化线程,并在容器加载所有 bean 后立即调用 init 线程。

【问题讨论】:

    标签: multithreading spring threadpool rabbitmq


    【解决方案1】:

    在我看来,您没有进行正确的异常处理。您说“线程默默地消失”,但这在 Java 中不会发生。我会审核您的异常并注意以下问题:

    • 注意throws Exception 的方法。这隐藏了各种邪恶。方法通常应该枚举它抛出的异常。
    • 如果一个异常引发了太多不同类型的异常,则表明它太大了。考虑将其拆分为多个较小的方法。或者在方法内部处理特定的异常并抛出一个异常。
    • 如果可能,尽量使用小的 try/catch 块来捕获单个异常。不要使用try { ... } catch (Exception e) { ... } 包含大量代码。这再次掩盖了邪恶。
    • 如果您发现异常,请确保您不只是盲目地继续。如果这是一个后台线程,那么它可能应该退出或重新启动套接字或者......
    • 确保您正确报告所有异常。每个 catch 块都应该对异常做一些事情。 e.printStackTrace() 可能有效,但通常需要提供有关问题的更多信息。

    但我不知道如何重新启动已停止的线程。

    您不会重新启动已停止的线程,而是启动另一个线程。如果线程根本不应该关闭,那么它需要重新打开一个套接字或者重新启动它的RabbitMQ 连接。同样,它是关于正确的异常处理。我不知道RabbitMQ,但类似下面的伪代码可能会有所帮助:

    public void run() {
        while (!shutdown) {
           Connection conn = null;
           try {
               conn = rabbitMq.start();
               processQueue(conn);
           } catch (IOException e) {
               // TODO: log the exception here
           } finally {
               // make sure we close the connection
               if (conn != null) { conn.close(); }
           }
           try {
              // we sleep here to not spin if the RabbitMQ host goes down
              Thread.sleep(1000);
           } catch (InterruptedException e) {
              Thread.currentThread.interrupt();
              // bail if someone interrupts us
              return;
           }
    }
    

    祝你好运。

    【讨论】:

    • 非常感谢 Gray.. 我现在可以解决问题了。我的印象是,一旦线程发生异常,它就会去 catch 块,然后线程被 JVM 声明。根据您的回答,显然不是这种情况。
    • 我从您的回答中了解到的是“即使发生异常,线程也处于活动状态(只要异常处理得当),一旦获得连接,它将继续尝试恢复连接它会做正常的事情” .....请确认我的理解是正确的
    • 是的,完全正确@Anupam。异常处理并不意味着任何东西都被杀死。只有到达run() 方法的结尾,线程才会消失——它永远不会静默。还要记住,主线程是相同的方式。
    • 只是最后一件事,而不是对上述评论的补充......“只有当 run() 方法结束时,线程才会消失”,如果异常没有正确处理,则异常保持沿着堆栈往下走,直到它达到最低点,即 JVM,因此突然死亡..
    • 当然,但这发生在run() 方法的末尾。只有当它是 RuntimeException 正弦时才会发生这种情况,否则它必须被捕获。
    【解决方案2】:

    如果您正确(“优雅地”)处理异常,那么线程将检索您的连接..只需将其放入 while true 循环并继续侦听队列..一旦网络连接(以及最终队列连接)将活着,那么您的线程将获得连接。

    【讨论】:

    • 你的答案对我来说似乎是正确的。但格雷斯的答案更详尽,更容易理解。
    猜你喜欢
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 1970-01-01
    • 1970-01-01
    • 2020-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多