gpt4 book ai didi

multithreading - Tomcat 7 异步处理

转载 作者:行者123 更新时间:2023-11-28 21:44:54 24 4
gpt4 key购买 nike

我想知道 Tomcat 7 是如何实现异步处理的。我理解为请求线程立即返回,让请求线程立即监听新的请求并响应。

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

最佳答案

您混淆了不同的概念。您必须区分:

  1. 按照 Servlet 3.0 处理异步请求;使您能够将传入的 servlet 请求与 Web 容器线程池分离的 API。它不会即时创建任何线程。实现适当的多线程解决方案取决于接口(interface)的用户。它与非阻塞 IO 无关。
  2. 线程池;提供了一种在 Web 容器中获取和管理线程的机制。对于异步请求处理,您有两种选择。您可以定义自己的 ExecutorService并使用它进一步处理请求,或者您可以创建一个新的 Runnable 并通过调用 AsyncContext.start() 将其提交给获得的 AsyncContext .对于 Tomcat,后一种方法使用 server.xml 中定义的 Tomcat 线程池。
  3. 非阻塞 IO (NIO);尽管它也是异步的,但这是另一回事。它与磁盘或网络 IO 等非阻塞 IO 操作有关。如果要为 HTTP 请求处理启用 NIO,请查看 Tomcat 的 documentation .

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

   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 简单示例

@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);
}
}

...和 ​​TestWorker

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);
}
}

关于multithreading - Tomcat 7 异步处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7287244/

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