Servlet的线程安全问题

Servlet是单例模式,自始至终创建一个对象,Tomcat是Servlet的容器,并且tomcat内部维护了一个线程池,Tomcat运用了IO多路复用技术实现,每个请求都会创建一个线程来进行处理。当多个请求同时访问同一个servlet对象时候,会创建多个线程对同一个对象进行操作,所以会产生线程安全问题。

方案1: 实现SingleThreadModel接口
我们可以让Servlet类实现SingleThreadModel接口,每个线程都会创建servlet实例,避免了多线程使用通过Servlet实例的请求,但是使用这种方式会导致对客户端的请求响应效率变低,增加了服务器因频繁创建和销毁Servlet实例的开销,因此此种方式不建议使用,已经过时。
方案2:使用synchronized同步锁
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
    synchronized (this) {
       // 业务代码
    }
}

建议:在Servlet实例中尽量不使用成员变量

如果将变量定义为成员变量,则这个变量在多个线程中是共享的,就有可能因为多个线程同时修改这个变量导致并发问题,因此我们可以将变量定义在处理业务的doXX方法中,定义为局部变量之后,每个线程都有属于自己的局部变量。

Servlet实例的生命周期

当客户端的请求到达Tomcat,Tomcat会创建一个线程来接收、处理、响应客户端请求,客户端在请求某个Servlet类时,线程需要通过这个Servlet类的实例来调用service方法、调用doGet/doPost..方法来处理响应请求,这个Servlet类的实例是何时创建、何时销毁的呢?
Servlet实例的生命周期指的是一个Servlet类的实例从创建到销毁的过程。
  1. Servlet类是单实例多线程的,一个Servlet类自始至终只会创建一个对象;

  2. 如果当前Servlet类没有配置

<load-on-startup>1</load-on-startup>:

当客户端第一次请求Servlet时,创建当前Servlet类的实例,然后使用这个实例调用service(ServletRequest, ServletResponse)方法——》service(HttpServletRequest, HttpServletResponse)方法——》doGet/doPost处理客户端请求;当客户端请求再次到达时将不会重新创建Servlet实例,直接使用第一次创建的实例调用方法进行响应;

  1. 如果当前Servlet类配置了

<load-on-startup>1</load-on-startup>:

当服务器启动时就会创建Servlet类的实例,无论客户端第一次请求这个Servlet类,还是再次请求都不会创建Servlet类实例,直接使用服务器启动时创建的Servlet实例来接收、处理、响应客户端请求;

  1. 当服务器关闭时,Serlvet类的实例会被销毁。

注意:配置<load-on-startup>1</load-on-startup>和不配置的区别是:配置了那么服务器在启动时就会把我们自己定义的Servlet对象创建出来。否则就要等到具体发起请求时才会创建对象。load-on-startup里的参数表示对象被创建的出来的顺序。

配置load-on-startup的两种方式:

- xml配置
<servlet>
    <servlet-name>TestServlet</servlet-name>
    <servlet-class>com.qfedu.servlets.TestServlet</servlet-class>
    <!--如果有多个Servlet都配置了load-on-startup,里面的数字就是在服务器中创建实例的顺序-->
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>TestServlet</servlet-name>
    <url-pattern>/test</url-pattern>
</servlet-mapping>
- 注解配置
@WebServlet(value = "/test",loadOnStartup = 1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值