首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异步servlet不异步工作

异步servlet不异步工作
EN

Stack Overflow用户
提问于 2014-03-04 18:38:53
回答 1查看 1.5K关注 0票数 4

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

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

代码语言:javascript
复制
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();
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-04 18:58:37

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

应采取以下步骤:

  • 从servlet ()方法中的web.xml中读取一些init参数,例如超时和线程池大小的
    • 超时参数用于设置异步线程的超时。
    • 线程池大小用于创建异步线程池。

  • 通过在AsyncContext ()或doPost()方法中调用HTTP request.startAsync()来获取doGet
  • 设置AsyncContext的超时
  • 附加侦听器以响应此AsyncContext的生命周期事件,如onComplete()、onTimeout()、onError()、onStartAsync()
  • 调用ExecutorService.execute()在后台线程中生成一些任务

试试这个示例代码。可能对你有帮助。

AsyncServletTaskProcessor:

代码语言:javascript
复制
import java.io.IOException;

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

public interface AsyncServletTaskProcessor {

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

TestServ:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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 */
    }

}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22180212

复制
相关文章

相似问题

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