servlet3.0的异步调用

要理解异步首先我们要理解几个概念
同步异步是针对应用程序和内核的交互而言的,同步指的是用户进程触发 IO 操作并
等待或者轮询的去查看 IO 操作是否就绪,而异步是指用户进程触发 IO 操作以后便开始做自己的事情,而当 IO 操作已经完成的时候会得到 IO 完成的通知。
以银行取款为例
同步 : 自己亲自出马持银行卡到银行取钱(使用同步 IO 时,Java 自己处理 IO 读写);
异步 : 委托一小弟拿银行卡到银行取钱,然后给你(使用异步 IO 时,Java 将 IO 读写
委托给 OS 处理,需要将数据缓冲区地址和大小传给 OS(银行卡和密码),OS 需要支持异步 IO操作 API)
阻塞非阻塞是针对于进程在访问数据的时候,根据 IO 操作的就绪状态来采取的不同
方式,说白了是一种读取或者写入操作方法的实现方式,阻塞方式下读取或者写入函数将一直等待,而非阻塞方式下,读取或者写入方法会立即返回一个状态值。
以银行取款为例
阻塞 : ATM 排队取款,你只能等待(使用阻塞 IO 时,Java 调用会一直阻塞到读写完
成才返回);
非阻塞 : 柜台取款,取个号,然后坐在椅子上做其它事,等号广播会通知你办理,没
到号你就不能去,你可以不断问大堂经理排到了没有,大堂经理如果说还没到你就不能去(使用非阻塞 IO 时,如果不能读写 Java 调用会马上返回,当 IO 事件分发器通知可读写时再继续进行读写,不断循环直到读写完成)

首先我们来想想servlet3.0之前的同步调用会有什么问题?
因为是同步调用,如何业务处理时间较长,线程会一直阻塞在那里,这样的话,其他的用户请求无法及时处理,因为tomcat的BIO模式下的线程数是有限的,即使是NIO也会有阻塞问题出现。所以servlet3.0出现了异步调用方式,可以及时释放主线程去接受其他的用户的请求,业务逻辑可以交给异步创建的线程去处理。

1、如果要支持异步调用servlet版本必须是3.0及以上

<dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
</dependency>

2、声明注解

@WebServlet(value = "/order",asyncSupported = true)

3、编写servlet

import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(value = "/order",asyncSupported = true)
public class DemoServlet extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
            System.out.println(Thread.currentThread()+"......");
            final AsyncContext asyncContext = req.startAsync();//返回异步类
            asyncContext.start(new Runnable() {//开启异步操作,有一个新线程去处理
                public void run() {
                    ServletResponse response = asyncContext.getResponse();//异步的response
                    try {
                        sleep();
                        asyncContext.complete();//异步调用完成
                        response.getWriter().write("成功");
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        System.out.println(Thread.currentThread()+".......");
    }

    public void sleep() throws InterruptedException {
        System.out.println(Thread.currentThread());
        Thread.sleep(5000);
    }
}

4、访问这个servlet控制台打印结果

在这里插入图片描述
我使用的是tomcat9,所以是nio,如果你使用的是tomcat7应该是bio模式
很明显可以看出来一个请求时由两个线程来处理的,这样的好处前文已经说了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值