可能是重复问题!我正在使用Tomcat作为我的服务器,想知道在Servlet中生成线程以实现确定性结果的最佳方法。我从一个Servlet操作中运行一些长时间运行的更新,并希望请求完成并且更新在后台中发生。除了添加像RabbitMQ这样的消息中间件之外,我认为我可以生成一个线程,在后台运行并按照自己的时间完成。我在其他SO线程中读到,服务器终止由服务器生成的线程,以便管理资源。
在使用Tomcat时,是否有推荐的生成线程或后台任务的方法?我还使用Spring MVC进行应用程序开发。
可能是重复问题!我正在使用Tomcat作为我的服务器,想知道在Servlet中生成线程以实现确定性结果的最佳方法。我从一个Servlet操作中运行一些长时间运行的更新,并希望请求完成并且更新在后台中发生。除了添加像RabbitMQ这样的消息中间件之外,我认为我可以生成一个线程,在后台运行并按照自己的时间完成。我在其他SO线程中读到,服务器终止由服务器生成的线程,以便管理资源。
在使用Tomcat时,是否有推荐的生成线程或后台任务的方法?我还使用Spring MVC进行应用程序开发。
ExecutorService
非常有帮助。Executors
类创建一个线程池:executor = Executors.newFixedThreadPool(10); // Max 10 threads.
然后在Servlet的service方法中(如果您不感兴趣,可以忽略结果,或者将其存储在会话中以供稍后访问):
Future<ReturnType> result = executor.submit(new YourTask(yourData));
YourTask
必须实现Runnable
或Callable
接口,可以像这样编写代码,其中yourData
是你的数据,例如填充请求参数值(请注意,绝对不应传递Servlet API工件,例如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.
如果您实际上正在使用像WildFly、Payara、TomEE等普通的JEE服务器,在那里EJB通常是可用的,那么您可以简单地在从servlet调用的EJB方法上放置@Asynchronous
注释。您还可以选择让它返回一个Future<T>
,其中AsyncResult<T>
作为具体值。
@Asynchronous
public Future<ReturnType> submit() {
// ... Do your job here.
return new AsyncResult<ReturnType>(result);
}
init()
和destroy()
中创建和关闭它们即可。否则,在ServletContextListener
中执行此操作确实更好,这样您就可以将其提供给更多的servlet。 - BalusCCallableTask
的构造函数参数传递即可。 - BalusCExecutors.newFixedThreadPool(n)
中所需的最大线程数?我正在运行一个多用户应用程序,我预计大多数用户会生成1-10个线程(可能更多)。但我不知道最终会有多少用户。 - Timo Ernstjava.util.concurrent
,后者使线程管理更加健壮。 - BalusC严格来说,根据Java EE规范,您不允许创建线程。如果多个请求同时到达,我还会考虑拒绝服务攻击(故意或无意)。
使用中间件解决方案肯定更加健壮和符合标准。