可能会重复!我正在使用 Tomcat 作为我的服务器,并且想知道在 servlet 中产生具有确定性结果的线程的最佳方法是什么。我正在从 servlet 操作运行一些长时间运行的更新,并希望完成请求并在后台进行更新。与其添加像 RabbitMQ 这样的消息中间件,我认为我可以生成一个可以在后台运行并在自己的时间完成的线程。我在其他 SO 线程中读到,服务器终止了服务器产生的线程,以便它能够很好地管理资源。
在使用 Tomcat 时,是否有推荐的生成线程、后台作业的方法。我还将 Spring MVC 用于应用程序。
最佳答案
在 Tomcat 或 Jetty 等准系统 servlet 容器中,您最安全的选择是使用具有最大线程数的应用程序范围的 线程池,以便任务在必要时排队。 ExecutorService
在这方面很有帮助。
在应用程序启动或 servlet 初始化时使用 Executors
创建一个类:
executor = Executors.newFixedThreadPool(10); // Max 10 threads.
然后在servlet的服务期间(你可以忽略你不感兴趣的情况下的结果,或者将它存储在 session 中以供以后访问):
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.
如果您实际上使用的是正常的 JEE 服务器,例如 WildFly、Payara、TomEE 等,而 EJB 通常可用,那么您可以简单地输入 @Asynchronous
您从 servlet 调用的 EJB 方法上的注释。您可以选择让它返回 Future<T>
与 AsyncResult<T>
作为具体值。
@Asynchronous
public Future<ReturnType> submit() {
// ... Do your job here.
return new AsyncResult<ReturnType>(result);
}
另见:
关于java - 从 Tomcat 中的 servlet 生成线程的推荐方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3745905/