gpt4 book ai didi

java - Servlet 3 的 Async Servlet 特性——我如何处理耗时的任务

转载 作者:行者123 更新时间:2023-11-30 09:07:20 25 4
gpt4 key购买 nike

最近在学习Servlet 3.0 Async Feature,主要思想是将绑定(bind)到Http Thread的任务释放到另一个Thread,这样Http Thread就可以回到Http Thread池(不会阻塞长任务processing ),那么你的应用程序可能会更有响应。这里一切顺利。


我找到了两种处理耗时任务的方法

  1. acontext.start()

      asyncContext.start(new Runnable() {
    @Override
    public void run() {
    serviceImpl(req, resp, adapter, context, isNotLeakScan);
    }
    });

    官方文档说:acontext.start(new Runnable() {...}) 从容器中获取一个新线程。

  2. 使用 BlockingQueue ,然后新建一个 Tread 来处理队列中的可运行对象。

    private static final BlockingQueue queue = new LinkedBlockingQueue();


    thread = new Thread(new Runnable() {
    @Override
    public void run() {
    while (true) {
    try {
    Thread.sleep(2000);
    AsyncContext context;
    while ((context = queue.poll()) != null) {
    try {
    ServletResponse response = context.getResponse();
    response.setContentType("text/plain");
    PrintWriter out = response.getWriter();
    out.printf("Thread %s completed the task",
    Thread.currentThread().getName());
    out.flush();
    } catch (Exception e) {
    throw new RuntimeException(e.getMessage(), e);
    } finally {
    context.complete();
    }
    }
    } catch (InterruptedException e) {
    return;
    }
    }


我的问题是:

  • 这两种方法有什么区别?

  • 第一个是否处理了 Tomcat 容器的任务管理(假设我们已经在 Tomcat 上部署了应用程序)

  • 第二种方式只是说明手动处理任务的方式?

最佳答案

区别在于:

(1) 在 servlet 线程池中执行缓慢的任务,导致 servlet 池饥饿(至少 Tomcat/Jetty 就是这种情况)。这意味着如果您将 serviceImpl(req, resp, adapter, context, isNotLeakScan); 替换为 Thread.sleep(Long.MAX_VALUE); 并尝试连接到从浏览器访问 Tomcat 200 次(默认线程数为 200)- Tomcat 将永远挂起,不再接受任何 HTTP 连接。

(2) 手动为每个任务生成一个线程。

您通常不想手动生成线程、轮询队列等。相反,您会使用 Executors 框架,它在引擎盖下实现了队列,并且基于内部线程池。

@WebServlet(urlPatterns = {"/slowServlet"}, asyncSupported = true)
public class SlowServlet extends javax.servlet.http.HttpServlet {

protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
final AsyncContext acontext = request.startAsync();
ServletContext appScope = request.getServletContext();
((Executor) appScope.getAttribute("executor")).execute(() -> {
try {
Thread.sleep(10000); // your slow running task
acontext.getResponse().getWriter().print("Done");
} catch (Exception e) {
e.printStackTrace();
}
});
}
}

而servlet context listener是(这里线程池的大小是硬编码的)

@WebListener
public class ExecutorListener implements ServletContextListener {

public void contextInitialized(ServletContextEvent sce) {
Executor executor = Executors.newFixedThreadPool(10);
sce.getServletContext().setAttribute("executor", executor);
}

public void contextDestroyed(ServletContextEvent sce) {
// add executor fancy shutdown logic here
}
}

关于java - Servlet 3 的 Async Servlet 特性——我如何处理耗时的任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24030366/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com