大概重复一遍!我正在使用Tomcat作为服务器,并且想知道什么是在servlet中产生确定性结果的最佳方式。我正在从servlet操作中运行一些长期运行的更新,并希望请求完成并在后台进行更新。我以为我可以生成一个可以在后台运行并在自己的时间内完成的线程,而不是添加像RabbitMQ这样的消息传递中间件。我在其他SO线程中读到,服务器终止了服务器派生的线程,以使其很好地管理资源。
使用Tomcat时,是否有建议的方法来生成线程,后台作业。我还将Spring MVC用于该应用程序。
在像Tomcat或Jetty这样的准系统servlet容器中,最安全的选择是使用最大 线程数 的applicaton宽 线程池 ,以便在必要时将任务排队。该ExecutorService是在这个非常有帮助。
ExecutorService
在应用程序启动或servlet初始化后,使用Executors该类创建一个:
Executors
executor = Executors.newFixedThreadPool(10); // Max 10 threads.
然后在servlet的服务期间(对于您不感兴趣的情况,您可以忽略结果,或将其存储在会话中以供以后访问):
Future<ReturnType> result = executor.submit(new YourTask(yourData));
当YourTask必须实现Runnable或者Callable,可以是这个样子,因此yourData只是你的数据,例如由请求参数值(一定要记住,你绝对不应该通过Servlet API的工件,如HttpServletRequest或HttpServletResponse沿!):
YourTask
Runnable
Callable
yourData
HttpServletRequest
HttpServletResponse
public class YourTask implements Runnable { private YourData yourData; public YourTask(YourData yourData) { this.yourData = yourData; } @Override public void run() { // Do your task here based on your data. } }
最后,在应用程序关闭或servlet销毁期间,您需要显式关闭它,否则线程可能会永远运行并阻止服务器正常关闭。
executor.shutdownNow(); // Returns list of undone tasks, for the case that.
如果您实际上使用的是通常可以使用EJB的普通JEE服务器(例如WildFly,Payara,TomEE等),则可以将@Asynchronous注释放在从Servlet调用的EJB方法上。您可以选择让它返回Future<T>带有的AsyncResult<T>具体值。
@Asynchronous
Future<T>
AsyncResult<T>
@Asynchronous public Future<ReturnType> submit() { // ... Do your job here. return new AsyncResult<ReturnType>(result); }