首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Tomcat 7异步处理

Tomcat 7异步处理
EN

Stack Overflow用户
提问于 2011-09-03 01:39:06
回答 1查看 19.1K关注 0票数 15

我想知道Tomcat7是如何实现异步处理的。我知道请求线程会立即返回,允许请求线程立即侦听新请求并对其进行响应。

“异步”请求是如何处理的?是否有单独的线程池来处理异步请求?为了提高性能,我假设阻塞IO是使用类似于java.nio.Selector的东西来处理的。在CPU计算中阻塞的线程怎么办?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-09-03 20:29:36

你混淆了不同的概念。您必须区分以下各项:

按照Servlet3.0API处理

  1. Asynchronous请求;使您能够将传入的Servlet请求从web容器线程池中解耦出来的。它不会在运行时创建任何线程。接口的用户需要实现一个适当的多线程解决方案。它与非阻塞IO.
  2. Thread池无关;提供了一种在web容器中获取和管理线程的机制。当涉及到异步请求处理时,您有两个选择。您可以定义自己的ExecutorService并使用它来进一步处理请求,也可以创建一个新的Runnable并通过调用AsyncContext.start()将其提交给获得的AsyncContext。对于Tomcat线程池,后一种方法使用在NIO( server.xml.
  3. Non-blocking )中定义的Tomcat线程池;尽管它也是异步的,但却是另一回事。它与磁盘或网络IO等非阻塞IO操作相关。如果希望为HTTP请求处理启用NIO,可以查看Tomcat的documentation.

下面的示例概述了它的工作原理。它只使用一个线程来处理工作任务。如果你从两个不同的浏览器并行运行它,输出如下所示(我使用一个自定义记录器):

代码语言:javascript
运行
复制
   DATE                         THREAD_ID  LEVEL      MESSAGE
2011-09-03 11:51:22.198 +0200      26        I:     >doGet: chrome
2011-09-03 11:51:22.204 +0200      26        I:     <doGet: chrome
2011-09-03 11:51:22.204 +0200      28        I:     >run: chrome
2011-09-03 11:51:27.908 +0200      29        I:     >doGet: firefox
2011-09-03 11:51:27.908 +0200      29        I:     <doGet: firefox
2011-09-03 11:51:32.227 +0200      28        I:     <run: chrome
2011-09-03 11:51:32.228 +0200      28        I:     >run: firefox
2011-09-03 11:51:42.244 +0200      28        I:     <run: firefox

您会看到doGet方法立即结束,而worker仍在运行。2个测试请求:http://localhost:8080/pc/TestServlet?name=chromehttp://localhost:8080/pc/TestServlet?name=firefox

简单示例Servlet

代码语言:javascript
运行
复制
@WebServlet(asyncSupported = true, value = "/TestServlet", loadOnStartup = 1)
public class TestServlet extends HttpServlet {
    private static final Logger LOG = Logger.getLogger(TestServlet.class.getName());
    private static final long serialVersionUID = 1L;
    private static final int NUM_WORKER_THREADS = 1;

    private ExecutorService executor = null;

    @Override
    public void init() throws ServletException {
        this.executor = Executors.newFixedThreadPool(NUM_WORKER_THREADS);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        final String name = request.getParameter("name");
        LOG.info(">doGet: " + name);

        AsyncContext ac = request.startAsync(); // obtain async context
        ac.setTimeout(0); // test only, no timeout

        /* Create a worker */
        Runnable worker = new TestWorker(name, ac);

        /* use your own executor service to execute a worker thread (TestWorker) */
        this.executorService.execute(worker);

        /* OR delegate to the container */
        // ac.start(worker);

        LOG.info("<doGet: " + name);
    }
}

...and the TestWorker

代码语言:javascript
运行
复制
public class TestWorker implements Runnable {
    private static final Logger LOG = Logger.getLogger(TestWorker.class.getName());
    private final String name;
    private final AsyncContext context;
    private final Date queued;

    public TestWorker(String name, AsyncContext context) {
        this.name = name;
        this.context = context;
        this.queued = new Date(System.currentTimeMillis());
    }

    @Override
    public void run() {

        LOG.info(">run: " + name);

        /* do some work for 10 sec */
        for (int i = 0; i < 100; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        ServletResponse response = this.context.getResponse();
        response.setContentType("text/plain");

        try {
            PrintWriter out = response.getWriter();
            out.println("Name:\t\t" + this.name);
            out.println("Queued:\t\t" + this.queued);
            out.println("End:\t\t" + new Date(System.currentTimeMillis()));
            out.println("Thread:\t\t" + Thread.currentThread().getId());
            out.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        this.context.complete();

        LOG.info("<run: " + name);
    }
}
票数 43
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7287244

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档