gpt4 book ai didi

java - 异步 servlet 不异步运行

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:05:33 24 4
gpt4 key购买 nike

我有一个 servlet,它接受一个请求并写一个长响应。响应位于使用 Thread.sleep(1000) 模拟长时间运行操作的循环中。我试图在这里设置一个异步请求,如代码所示。但它不起作用。当我向 servlet 调用多个请求时,它们都连续执行,而不是同时执行。我做错了什么?

虽然 servlet 应该是线程化的 - 每个对服务器的请求都会导致容器执行一个新线程(或重用池中的线程)。

package test;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javax.servlet.AsyncContext;

import javax.servlet.annotation.WebServlet;

@WebServlet(urlPatterns={"/test"}, asyncSupported=true)
public class TestServ extends HttpServlet {

@Override
public void doGet(HttpServletRequest rq, HttpServletResponse rs){

rs.setContentType("text/plain");
rs.setHeader("Access-Control-Allow-Origin", "*");


AsyncContext asy = rq.startAsync(rq, rs);
asy.start(new Client(asy));
}


@Override
public String getServletInfo() {
return "Short description";
}
}

class Client implements Runnable {

private int counter = 0;
private AsyncContext asy;

Client(AsyncContext asy) {
this.asy = asy;
}

@Override
public void run() {
//run long task here
try {
PrintWriter out = asy.getResponse().getWriter();
while (counter < 5) {

out.println(counter++ + 1);
Thread.sleep(1000);

}

} catch (Exception ex) {

} finally{
asy.complete();
}
}
}

最佳答案

使用方法 ExecutorService.execute() 在后台线程中生成一些任务。

要遵循的步骤:

  • 在 servlet init() 方法中从 web.xml 中读取一些初始化参数,例如 timeout 和 threadpoolsize
    • timeout参数用于设置Async线程的超时时间
    • threadpoolsize 用于创建异步线程池
  • 在 doGet() 或 doPost() 方法中调用 HTTP request.startAsync() 获取 AsyncContext
  • 设置AsyncContext的超时时间
  • 附加监听器以响应此 AsyncContext 的生命周期事件,例如 onComplete()、onTimeout()、onError()、onStartAsync()
  • 调用 ExecutorService.execute() 在后台线程中生成一些任务

试试这个示例代码。它可能对您有所帮助。

AsyncServletTaskProcessor:

import java.io.IOException;

import javax.servlet.AsyncContext;
import javax.servlet.ServletException;

public interface AsyncServletTaskProcessor {

void process(AsyncContext ctx) throws IOException, ServletException;
}

测试服务:

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = { "/test" }, asyncSupported = true)
public class TestServ extends HttpServlet implements AsyncServletTaskProcessor{

/** The exec. */
private ExecutorService exec;

public int CALLBACK_TIMEOUT;

public void init() throws ServletException {
// read callback timeout form web.xml as init parameter
CALLBACK_TIMEOUT = Integer.parseInt(getInitParameter("timeout"));
// read thread pool size form web.xml as init parameter
int size = Integer.parseInt(getInitParameter("threadpoolsize"));
exec = Executors.newFixedThreadPool(size);

}

@Override
public void doGet(HttpServletRequest rq, HttpServletResponse rs) {

rs.setContentType("text/plain");
rs.setHeader("Access-Control-Allow-Origin", "*");

//AsyncContext asy = rq.startAsync(rq, rs);
//asy.start(new Client(asy));

final AsyncContext asy = rq.startAsync();

// set the timeout
asy.setTimeout(CALLBACK_TIMEOUT);

// attach listener to respond to lifecycle events of this AsyncContext
asy.addListener(new AsyncListenerImpl(asy));

// spawn some task in a background thread
exec.execute(new AsyncServletTaskRunner(asy, this));
}

@Override
public String getServletInfo() {
return "Short description";
}

@Override
public void process(AsyncContext ctx) throws IOException, ServletException {
//do whatever you want to do as process of each thread
}
}

AsyncServletTaskRunner:

import javax.servlet.AsyncContext;

public class AsyncServletTaskRunner implements Runnable {

/** The ctx. */
private AsyncContext ctx;

/** The processor. */
private AsyncServletTaskProcessor processor;

public AsyncServletTaskRunner() {
super();
}

public AsyncServletTaskRunner(AsyncContext ctx, AsyncServletTaskProcessor processor) {
this.ctx = ctx;
this.processor = processor;
}

@Override
public void run() {

try {
processor.process(ctx);
} catch (Exception e) {
try {
// redirect to error page or do whatever is needed
} catch (Exception e1) {
e1.printStackTrace();
}
} finally {
ctx.complete();
}
}

public AsyncContext getCtx() {
return ctx;
}

public void setCtx(AsyncContext ctx) {
this.ctx = ctx;
}

}

AsyncListenerImpl:

import java.io.IOException;

import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;

public class AsyncListenerImpl implements AsyncListener {

/** The ctx. */
private AsyncContext ctx;

public AsyncListenerImpl() {
super();
}

public AsyncListenerImpl(AsyncContext ctx) {
this.ctx = ctx;
}

@Override
public void onComplete(AsyncEvent event) throws IOException {
/** complete() has already been called on the async context, nothing to do */
}

@Override
public void onTimeout(AsyncEvent event) throws IOException {
/** timeout has occured in async task... handle it */
try {
// redirect to error page or do whatever is needed
} catch (Exception e1) {
e1.printStackTrace();
} finally {
ctx.complete();
}
}

@Override
public void onError(AsyncEvent event) throws IOException {
/** THIS NEVER GETS CALLED - error has occured in async task... handle it */
try {
// redirect to error page or do whatever is needed
} catch (Exception e1) {
e1.printStackTrace();
} finally {
ctx.complete();
}
}

@Override
public void onStartAsync(AsyncEvent event) throws IOException {
/** async context has started, nothing to do */
}

}

关于java - 异步 servlet 不异步运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22180212/

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