servlet 多线程

来源:互联网 发布:淘宝店铺推广技巧 编辑:程序博客网 时间:2024/06/05 12:39

servlet 并不是多线程安全的 。 


servlet 模式是多线程 单实例的 。


当servlet 容器(tomcat ,jboss)对 servlet 初始化以后 默认配置的情况下有且只有一个servlet instance ,我猜 :默认的初始化就是单例模式 。


所以针对同一个url的多个并发请求就会复用这个 servlet instance 。


因为用的是同一个instance ,所以实例变量 ,静态变量都是共享的 。程序对实例变量,静态变量的更改,使用都会导致混淆 。


但是方法变量 ,块变量 是安全的 。 所以 确保 servlet 中不使用 实例变量+静态变量就能保证多线程安全。 


从Java 内存模型也可以知道,方法中的临时变量是在栈上分配空间,而且Servlet多线程中每个线程都有自己私有的栈空间,所以它们不会影响线程的安全。


Servlet 3.0 之前,一个普通 Servlet 的主要工作流程大致如下:首先,Servlet 接收到请求之后,可能需要对请求携带的数据进行一些预处理;接着,调用业务接口的某些方法,以完成业务处理;最后,根据处理的结果提交响应,Servlet 线程结束。其中第二步的业务处理通常是最耗时的,这主要体现在数据库操作,以及其它的跨网络调用等,在此过程中,Servlet 线程一直处于阻塞状态,直到业务方法执行完毕。在处理业务的过程中,Servlet 资源一直被占用而得不到释放,对于并发较大的应用,这有可能造成性能的瓶颈。对此,在以前通常是采用私有解决方案来提前结束 Servlet 线程,并及时释放资源。


在同步 的情况下 servlet 多个线程会阻塞 ,导致并发数量有限 !!!


Servlet 3.0 针对这个问题做了开创性的工作,现在通过使用 Servlet 3.0 的异步处理支持,之前的 Servlet 处理流程可以调整为如下的过程:首先,Servlet 接收到请求之后,可能首先需要对请求携带的数据进行一些预处理;接着,Servlet 线程将请求转交给一个异步线程来执行业务处理,线程本身返回至容器,此时 Servlet 还没有生成响应数据,异步线程处理完业务以后,可以直接生成响应数据(异步线程拥有 ServletRequest 和 ServletResponse 对象的引用),或者将请求继续转发给其它 Servlet。如此一来, Servlet 线程不再是一直处于阻塞状态以等待业务逻辑的处理,而是启动异步线程之后可以立即返回。


但是有的人走的更远,他们抛弃了servlet 接受 http请求的方式,开发了新的框架。 


jboss 的 netty 就是针对高并发的一个可选解决方案 ,方案关键字 : channel ,      buffer  , even model .

原创粉丝点击