我是否需要在实现MessageListener类的类的onMessage方法中关闭执行程序?

时间:2017-06-02 07:45:48

标签: java spring

我有一个使用Spring框架的Java应用程序。它是一个监听器应用程序,可以非常快速地使用线程异步地从某个源获取消息,并将保存到数据库中。

我正在使用ExecutorService,它在Servlet类中初始化并存储在可由onMessage()方法访问的静态变量中。

我想知道的是,如果我总是收到消息,是否需要关闭ExecutorService。如果事实证明我需要关闭执行程序,我应该把它放在哪里?

@Override
public void onMessage(Message message) {
    String msg = "";
    ExecutorService taskExecutor;

    try {
        taskExecutor = StartupServlet.taskManager.getExecutor();
        msg = extractMessage(message);
        taskExecutor.execute(new MessageTask(msg));
        // Where do I place taskExecutor.shutdown();? Doing so here will reject the succeeding tasks, which breaks the listener.
    } catch (Exception e) {
        e.printStackTrace();
    }
}

我正在使用Spring Beans来初始化线程,它运行正常。我只是不确定我是应该关闭它还是根本不关闭它。

<bean id="taskManager" class="com.company.threading.TaskManager">
    <property name="executor" ref="executorService"/>
</bean>

<bean id="executorService" 
      class="java.util.concurrent.Executors" 
      factory-method="newFixedThreadPool" 
      destroy-method="shutdown">
    <constructor-arg value="5"/>
</bean>

谢谢。

1 个答案:

答案 0 :(得分:1)

假设com.company.threading.TaskManager是您的自定义类,您不需要在shutdown内调用onMessage,因为如果这样做,您将无法处理其他消息。

您需要做的是在Spring上下文关闭时优雅地终止执行程序

@Component
public class ContextClosedHandler implements ApplicationListener<ContextClosedEvent> {

    @Autowired
    @Qualifier("executorService")
    private ExecutorService executor;

    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        executor.shutdown();
        try {
            // define how much time to wait for the completion
            if (!executor.awaitTermination(15, TimeUnit.MINUTES)) { 
                List<Runnable> incompleteTask = executor.shutdownNow();
                // do that you want with them
            }
        } catch (InterruptedException e) {
            // handle or log exception
        }
    }
}

另外,我建议你不要使用静态对象来获取像StartupServlet.taskManager.getExecutor()这样的执行器实例。让春天为你做到!

@Autowired
@Qualifier("executorService")
private ExecutorService executor;

希望它有所帮助!