Java 使用spring amqp ListenerContainer关闭应用程序会挂起或花费很长时间

Java 使用spring amqp ListenerContainer关闭应用程序会挂起或花费很长时间,java,spring,rabbitmq,spring-amqp,Java,Spring,Rabbitmq,Spring Amqp,我创建了一个简单的“Hello World”风格的应用程序来测试spring amqp和RabbitMQ。Spring上下文是使用ClassPathXmlApplicationContext从主函数加载的,它启动amqp并设置一个ListenerContainer,侦听队列上的消息并在指定的pojo上调用指定的方法。除了关闭应用程序外,一切正常。我在spring上下文中尝试了close()方法,该方法开始关闭ListenerContainer,关闭工作线程,但随后应用程序挂起,并且没有退出。我还

我创建了一个简单的“Hello World”风格的应用程序来测试spring amqp和RabbitMQ。Spring上下文是使用
ClassPathXmlApplicationContext
从主函数加载的,它启动amqp并设置一个ListenerContainer,侦听队列上的消息并在指定的pojo上调用指定的方法。除了关闭应用程序外,一切正常。我在spring上下文中尝试了
close()
方法,该方法开始关闭ListenerContainer,关闭工作线程,但随后应用程序挂起,并且没有退出。我还尝试了上下文上的
stop()
,以及ListenerContainer bean上的
shutdown()

问题: 如何干净地关闭具有spring amqp ListenerContainers的spring上下文

以下是关机期间的日志输出:

Jul 07, 2014 1:00:22 AM org.springframework.context.support.ClassPathXmlApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@472a2a50: startup date [Mon Jul 07 01:00:08 CEST 2014]; root of context hierarchy
Jul 07, 2014 1:00:22 AM org.springframework.context.support.DefaultLifecycleProcessor stop
INFO: Stopping beans in phase 2147483647
Jul 07, 2014 1:00:22 AM org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer doShutdown
INFO: Waiting for workers to finish.
Jul 07, 2014 1:00:23 AM org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer doShutdown
INFO: Successfully waited for workers to finish.
此输出后,应用程序挂起且不退出

以下是主要方法:

public static void main(String[] args) {
    final ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:app-config.xml");
    ctx.registerShutdownHook();
    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            System.out.println("Quitting from Main...");
            ctx.close();
        }
    }, 10000);
}
下面是app-config.xml

<beans ...>
    <context:annotation-config />
    <import resource="amqp-config.xml" />
    <bean id="messageReceiver" class="com.knesek.amqp.spring.MessageReceiver" />
</beans>

以及spring amqp相关配置(amqp config.xml):



听起来您有一些非守护进程线程使您的上下文保持活动状态。关闭上下文将停止任何框架线程。我建议您使用jstack/visualvm进行线程转储。

在调查线程转储后,似乎
计时器
等待安排新任务会阻止关闭。在
ctx.close()之前添加
timer.cancel()
解决了问题。你的回答让我找到了解决办法,所以我接受了。
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
       xmlns="http://www.springframework.org/schema/rabbit" ...>

    <connection-factory id="connectionFactory" username="guest" password="guest" host="127.0.0.1"/>
    <template id="amqpTemplate" connection-factory="connectionFactory"/>
    <admin connection-factory="connectionFactory" />
    <direct-exchange name="incomingMessages">
        <bindings>
            <binding key="messages.inbound" queue="inboundMsgs"/>
        </bindings>
    </direct-exchange>
    <listener-container id="listenerContainer" connection-factory="connectionFactory"  >
        <listener ref="messageReceiver" method="receiveMessage" queues="inboundMsgs"  />
    </listener-container>
    <queue name="inboundMsgs"/>
</beans:beans>