如何现实servlet的单线程模式

 这个面试题挺经典的,但是网上不少朋友的回答题不达意,因此我在这里就这个问题作一下探讨。

          网上朋友的回答是加入<%@ page isThreadSafe=”false”%>这条命令。天啊,我晕!这是什么命令?是jsp的命令啊,怎么会加入到servlet中呢?固然了,jsp的运行实质是servlet机制,这条命令是jsp页面告诉容器编译“我”的时候实现单线程。那咱们看看他编译后的servlet类和之前的servlet有什么不一样?没有加入这条指令的页面中servlet类定义是:面试

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

………………………………//内部实现我们大能够不看他。
}安全

而加入这个命令以后的类定义是:session

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

…………………………//一样省略实现细节性能

}线程

        我想你们应该很清楚的发现:加入<@page isThreadSafe="false">以后servlet是实现了SingleThreadModel接口的。有兴趣的朋友能够查下相关资料,其实这个接口在servlet2.4以后就废除了。那么为何废除?实现了这个接口查看代码内容的时候却发现什么方法都没添加,为何?接口

       其实这个接口只是一个标识,让容器改变servlet生成策略的。同步

  默认的,servlet容器是只建立servlet単实例,为请求提供线程池,咱们为了能保证servlet的线程安全问题而不在servlet中添加实例属性。servlet

       可是若是一个servlet实现了SingleThreadModel接口那容器在建立实例池,为每一个求情分配实例,当用户请求结束时将实例归还实例池。

       这样作真的安全吗?非也!由于每一个请求都会分发一个servlet实例,对于同用户下分发的不一样的servlet来讲极可能用到同一个session中的属性数据,这样固然出现了线程同步的问题,是不安全的!并且不一样用户也可能享用同一个context中的数据,也是不安全的。因而在servlet2.4中建议再也不使用这样的设置。

  这样一来咱们知道:若是非要实现servlet单线程那就要在servlet中实现SingleThreadModel接口,在jsp中添加<@ page isThreadSafe="false">命令。可是这是不被提倡的。

  也有网友疑问:让servlet单线程而多实例原本不是为了线程安全的吗?为何<@ page isThreadSafe=?>?的答案倒是false?

  我以为这是个误区,这样设置真的是单线程吗?那确定不是了,其实这个设置只是要容器保证同一时刻只有一个线程能在servlet的service方法中执行,由于默认的容器实例化servlet时时単实例,若是同时只有一个线程去管理这个惟一的servlet实例,那性能将是极其慢的,为了解决这个问题,容器采起了servlet实例池的方式。每一个请求一个线程,而一个线程一个servlet。

         由于这种方式并非线程安全的,因此答案是false。

  终上所述:其实这道题目是指若是让一个servlet实例对应一个线程,而不是一个servlet实例对应多个线程的默认方式。