学习笔记:Sevlet3异步 和 Spirng对Servlet3

2021-01-16  本文已影响0人  瓢鳍小虾虎

使用异步机制处理请求是非常有用的,可以更好的利用cpu资源,提高程序吞吐量。因为通常的请求处理都是单线程的,请求线程是由tomcat分配的,如果业务处理要经过io操作等耗时较长的任务,线程就会一直被占用,tomcat线程池容易被占满,但是cpu并没有充分发挥效能。

Servlet3提供了对请求异步处理的机制。底层就是利用FutureTask的原理。Spirng框架也对Servlet3做了封装,从而更方便开发者使用。

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;
import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@WebServlet(value = "/servlet3/test", asyncSupported = true)
public class Servlet3Demo extends HttpServlet {
    private static ThreadPoolExecutor executor =
            new ThreadPoolExecutor(100, 200, 5000L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(200));

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        AsyncContext asyncContext = req.getAsyncContext();

        // 记得使用线程池控制多线程操作。
        executor.execute(() ->{
            try {
                Thread.sleep(1000L); // 模拟业务
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            try {
                asyncContext.getResponse().getWriter().write("response string");
            } catch (IOException e) {
                e.printStackTrace();
            }
            asyncContext.complete();
        });

//        asyncContext.start(() -> {
//            try {
//                Thread.sleep(1000L); // 模拟业务
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//
//            try {
//                asyncContext.getResponse().getWriter().write("response string");
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            asyncContext.complete();
//        });
    }
}
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@RestController
public class SpringSevlet3ControllerDemo {
    private LinkedBlockingDeque<DeferredResult> quene = new LinkedBlockingDeque<>();
    ThreadPoolExecutor executor =
            new ThreadPoolExecutor(100, 200, 5000L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(200));

    @GetMapping("/deferredresult/test")
    public DeferredResult<String> getSomeResult() {
        final DeferredResult<String> deferredResult = new DeferredResult<>(3000L); // 超时时间3秒

        quene.add(deferredResult);

        executor.submit(()->{
            try {
                Thread.sleep(1000L); // 模拟业务
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            String rs = "结果123";

            deferredResult.setResult(rs);
        });

        deferredResult.onTimeout(()->{
            // 超时业务代码
            String rs = "超时了";
            deferredResult.setResult(rs);
        });

        deferredResult.onCompletion(()->{
            // 完成后,移除quene队列
            quene.remove();
        });

        return deferredResult;
    }

    @Scheduled(fixedRate = 1000)
    public void scheduleResult(){ // 扫描队列
        for (int i = 0; i <quene.size() ; i++) {
            DeferredResult<String> stringDeferredResult = quene.poll();
            stringDeferredResult.setResult("result:"+i);
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读