从 Tomcat 中的 servlet 生成线程的推荐方法是什么 [英] What is recommended way for spawning threads from a servlet in Tomcat

查看:23
本文介绍了从 Tomcat 中的 servlet 生成线程的推荐方法是什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能是重复!我使用 Tomcat 作为我的服务器,并想知道在具有确定性结果的 servlet 中生成线程的最佳方法是什么.我正在从 servlet 操作运行一些长时间运行的更新,并希望完成请求并在后台进行更新.与其添加像 RabbitMQ 这样的消息中间件,我想我可以生成一个可以在后台运行并在自己的时间完成的线程.我在其他 SO 线程中读到,服务器终止了服务器产生的线程,以便它能够很好地管理资源.

Probably a repeat! I am using Tomcat as my server and want to know what is best way to spawn threads in the servlet with deterministic outcomes. I am running some long running updates from a servlet action and would like for the request to complete and the updates to happen in the background. Instead of adding a messaging middleware like RabbitMQ, I thought I could spawn a thread that could run in the background and finish in its own time. I read in other SO threads that the server terminates threads spawned by the server in order for it to manage resources well.

在使用 Tomcat 时,是否有推荐的产生线程、后台作业的方法.我还为应用程序使用了 Spring MVC.

Is there a recommended way of spawning threads, background jobs when using Tomcat. I also use Spring MVC for the application.

推荐答案

在像 Tomcat 或 Jetty 这样的准系统 servletcontainer 中,最安全的选择是使用具有最大线程数的应用程序范围的线程池,以便任务将在必要时排队.ExecutorService 在这方面很有帮助.

In a barebones servletcontainer like Tomcat or Jetty, your safest bet is using an applicaton wide thread pool with a max amount of threads, so that the tasks will be queued whenever necessary. The ExecutorService is very helpful in this.

在应用程序启动或 servlet 初始化时,使用 Executors 类来创建一个:

Upon application startup or servlet initialization use the Executors class to create one:

executor = Executors.newFixedThreadPool(10); // Max 10 threads.

然后在servlet的服务期间(如果你不感兴趣,可以忽略结果,或者将其存储在会话中以供以后访问):

Then during servlet's service (you could ignore the result for the case that you aren't interested, or store it in the session for later access):

Future<ReturnType> result = executor.submit(new YourTask(yourData));

其中 YourTask 必须实现 RunnableCallable 并且看起来像这样,其中 yourData 只是你的数据,例如填充请求参数值(请记住,您绝对不应传递 Servlet API 工件,例如 HttpServletRequestHttpServletResponse!):

Where YourTask must implement Runnable or Callable and can look something like this, whereby yourData is just your data, e.g. populated with request parameter values (just keep in mind that you should absolutely not pass Servlet API artifacts such as HttpServletRequest or HttpServletResponse along!):

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 销毁期间,您需要明确关闭它,否则线程可能永远运行并阻止服务器正确关闭.

Finally, during application's shutdown or servlet's destroy you need to explicitly shutdown it, else the threads may run forever and prevent the server from properly shutting down.

executor.shutdownNow(); // Returns list of undone tasks, for the case that.

如果您实际上使用的是普通的 JEE 服务器,例如 WildFly、Payara、TomEE 等,其中 EJB 通常可用,那么您可以简单地将 @Asynchronous 注释放在 EJB 方法上您从 servlet 调用.您可以选择让它返回一个 Future,其中 AsyncResult 作为具体值.

In case you're actually using a normal JEE server such as WildFly, Payara, TomEE, etc, where EJB is normally available, then you can simply put @Asynchronous annotation on an EJB method which you invoke from the servlet. You can optionally let it return a Future<T> with AsyncResult<T> as concrete value.

@Asynchronous
public Future<ReturnType> submit() {
    // ... Do your job here.

    return new AsyncResult<ReturnType>(result);
}

另见:

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆