深入理解Servlet机制——Servlet单线程模式

最近看到一道面试题:如何实现Servlet单线程模式?   一看到这个问题就楞了,都搞不懂这道题的真实意思,所以就去网上找资料,在这里总结一下,加深记忆。

1、Servlet多线程及如何处理线程安全

Servlet的生命周期是由Web容器负责的,可以通过配置文件设置初始化Servlet的时间,在这里不详细谈,大家可以访问http://链接仔细研究。Web容器在实例化Servlet时,默认的是单实例,即一个Servlet只有一个实例对象。大家思考一下,仅仅一个单实例是如何实现多个相同请求?这就用到了多线程。Servlet默认就是单实例,多线程,即Servlet提供线程池。即实例一次,处理多个相同请求(一个请求对应一个线程),相当于是多个线程执行同一个Servlet。这样以来就出现线程安全问题(http://baike.baidu.com/view/1298606.htm),因此Servlet也就不是线程安全的了。如何处理线程安全呢?有三种方法,大家可以看一下http://blog.csdn.net/explorering/article/details/1330744这个链接的内容,Servlet中常用的就是上面链接文章里提到的第三种-避免使用实例变量,即使用局部变量。因为方法中的临时变量即局部变量是在栈里分配空间,而每个线程有它们自己的栈空间,这样局部变量就不会影响到线程安全问题了。


2、Servlet如何实现单线程

去网上查资料,大家的回答都是一样的,就是在JSP页面开始写这样一行代码:<%@ page isThreadSafe="fase"%>(已经不提倡用)。JSP是页面,Servlet是Java类,为何加上<%@ page isThreadSafe="fase"%>这行代码Servlet就实现单线程呢?这就要了解JSP运行机制了,JSP运行实质是Servlet,这条命令是JSP告诉编译器:在编译“我”的时候要实现SingleThreadModel接口实现Servlet单线程。就这样Servlet就实现了单线程。单线程Servlet与默认Servlet有哪些区别呢?接下来咱们看看代码:

没加<%@ page isThreadSafe="fase"%>命令的JSP编译后的Servlet

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase 
      implements org.apache.jasper.runtime.JspSourceDependent{

       ..........//内部怎么实现的不用看

}

加<%@ page isThreadSafe="fase"%>命令的JSP编译后的Servlet

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase 
       implements org.apache.jasper.runtime.JspSourceDependent,SingleThreadModel{

       ..........//内部怎么实现的不用看

}

通过上面两块代码就清楚的发现,加上<%@ page isThreadSafe="fase"%>之后的JSP被编译生成的Servlet就实现了SingleThreadModel接口。SingleThreadModel接口页面没有方法,只是一个标识,让容器改变Servlet生成策略的。这个借口在Servlet2.4之后就废除了,可能是因为这个接口什么方法也没有。

即使Servlet实现单线程,但是Web容器在初始化Servlet时还是单实例,就是上面咱们提到的Web容器默认的就是Servlet单实例。

大家考虑这样一个情况:一个Servlet对应多个URL映射,那么会生成一个还是多个Servlet实例?如果是多个实例,那和Web容器默认Servlet单实例有矛盾吗?

Servlet单线程怎么处理同时多个请求呢?只有当上个请求被处理完后才执行第二个请求。

看这条命令<% page isThreadSafe="fase" %>,它清楚的告诉我们Servlet单线程不是线程安全的,为什么不线程安全呢?这个还没有搞清楚,请大家赐教!


你可能感兴趣的:(Servlet)