2011-04-20 83 views
2

我有一个处理特定传入请求的servlet。我们将其称为`UpdateUserStats'。我希望通话速度快,但我也需要请求执行相当昂贵的任务。我认为如果让UpdateUserStats servlet执行所有确定成功或失败的工作,坚持新的状态,然后为后台线程排队一些工作以便立即处理并返回成功,这可能是一个很好的解决方案。Java,Tomcat,ServletContextListener和后台线程

这看起来不错,但我想知道如何处理关机。当服务器关闭时,我想确保它不会杀死后台线程,直到没有更多的工作。我正在考虑使用tomcat ServletContextListener来让后台线程知道服务器正在关闭,并且一旦队列结束就退出了,但我不能100%确定这将会如何工作。请求contextDestroyed()只有在所有请求都完成处理后?界面似乎暗示了这一点,但我没有在文档中找到它。另外,我不知道Tomcat在生气之前愿意等待多久,后台线程没有终止。

或者,有没有更好的方法来处理这个问题?如果Spring有一些神奇的后请求后台工作功能,那么这是一个Spring应用程序。

回答

1

基于Servlet规范文档

“在应用程序关闭,听众以相反的顺序通知其申报 与通知会话监听前述通知上下文监听。会议的听众必须在上下文监听器 被通知应用程序关闭之前被通知会话失效。“

因此,这应该是第一个处理通知线程完成其工作的侦听器。

我已经使用了tomcat,并且至今我已经看到,如果侦听器尚未完成,那么在放弃执行干净关闭之前,它不会等待超过10-15秒。

通常像Spring这样的所有容器在关机期间使用监听器进行干净的出口

1

提及替代方法,您可以在单独的JVM中创建队列(使用ActiveMQ,RabbitMQ或更简单的东西)。这样,即使tomcat出现故障,任务也会被处理。

1

您可以使用ThreadPool,并在应用程序范围内使用最大线程数,然后它将在必要时排队,并且可以根据硬件和线程任务进行配置。对于需要使用的ExecutorService:http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html

线程池可以初始化如下

executorPool = Executors.newFixedThreadPool(50);

在你的服务方法中,你可以定义提交给线程如下: executorPool.submit(new ProcessTask());

清理ThreadPool可以在销毁/关闭(应用程序)期间完成,如下所示: executorPool.shutdownNow();

希望这是很有帮助的