Servlet的线程安全

一、什么是Servlet的线程安全

  1.在Servlet的整个生命周期中,构造方法只被执行一次。也就是说,在Servlet的整个生命周期中,只存在一个Servlet实例对象。这说明Servlet是单例多线程的,可能会引起线程安全问题。

所谓线程安全就是一个Servlet实例对象会同时处理多个请求,这样的Servlet工作效率的确很高。但如果Servlet中包含成员变量的话,可能一个线程对该成员变量进行写操作,而另一个线程对该成员变量进行读操作。所以,单例多线程的Servlet不能创建成员变量。

  下面我将通过例子讨论线程安全问题(不存在线程安全问题的代码:)

 package gacl.servlet.study;

 import java.io.IOException;

 import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* 当多线程并发访问这个方法里面的代码时,会存在线程安全问题吗??
* i变量被多个线程并发访问,但是没有线程安全问题,因为i是doGet方法里面的局部变量,
* 当有多个线程并发访问doGet方法时,每一个线程里面都有自己的i变量,
* 各个线程操作的都是自己的i变量,所以不存在线程安全问题
* 多线程并发访问某一个方法的时候,如果在方法内部定义了一些资源(变量,集合等)
* 那么每一个线程都有这些东西,所以就不存在线程安全问题了
*/
public class ServletThread extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
int a=1;
a++;
response.getWriter().write(a);
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
} }

存在线程安全问题的代码:

 package gacl.servlet.study;

 import java.io.IOException;

 import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class ServletTreadDemo extends HttpServlet { int i=1;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
i++;
try {
Thread.sleep(1000*3);
} catch (InterruptedException e) {
e.printStackTrace();
}
response.getWriter().write(i+"");
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
} }

把i定义成全局变量,多个线程并发访问变量全局变量 i 时,就会存在线程安全问题了,如果同时开启两个浏览器模拟并发访问同一个Servlet,本来正常来说,第一个浏览器应该看到2,而第二个浏览器应该看到3的,结果两个浏览器都看到了3。

2.线程安全问题的解决办法:

1.加锁(synchronized)

  加了synchronized后,并发访问i时就不存在线程安全问题了,为什么加了synchronized后就没有线程安全问题了呢?假如现在有一个线程访问Servlet对象,那么它就先拿到了Servlet对象的那把锁等到它执行完之后才会把锁还给Servlet对象,由于是它先拿到了Servlet对象的那把锁,所以当有别的线程来访问这个Servlet对象时,由于锁已经被之前的线程拿走了,后面的线程只能排队等候了。。这样不科学。。如果有1000人同时访问ServletThreadDemo1。后面的人还不等得得吐血!!

 package gacl.servlet.study;

 import java.io.IOException;

 import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class ServletThreadDemo1 extends HttpServlet { int i=1;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
synchronized (ServletThreadDemo1.class) {//在java中,每一个对象都有一把锁,这里的this指的就是Servlet对象
i++;
try {
Thread.sleep(5000*2);
} catch (InterruptedException e) {
e.printStackTrace();
}
response.getWriter().println(i+"");
} } public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

2.sun公司给的解决方案是:如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。 SingleThreadModel接口中没有定义任何方法,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。 对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象。 但是实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。事实上,在Servlet API 2.4中,已经将SingleThreadModel标记为Deprecated(过时的)。

Servlet的线程安全的更多相关文章

  1. Servlet 是否线程安全 看完便知

    Servlet 是否线程安全 看完便知 转自:http://blog.sina.com.cn/s/blog_6448959f0100kct7.html     摘 要:介绍了Servlet多线程机制, ...

  2. 玩转Web之servlet(五)---- 怎样解决servlet的线程安全问题

    servlet默认是存在线程安全问题的,但是说白了,servlet的线程安全问题实际上就是多线程的线程安全问题,因为servlet恰巧是一个多线程才会出现安全性问题. 浏览器每次通过http协议去提交 ...

  3. servlet是线程安全的么

    servlet生命周期 三个重要方法 1  init() 进行资源的加载 2 service() 处理请求,根据请求方式,调用doGet或者doPost 3 destroy() 进行资源的释放 ser ...

  4. 漫画 | Servlet属于线程安全的吗?

    Servlet属于线程安全的吗? Servlet不是线程安全的 在JSP中,只有一行代码:<%=A+B %>,运行结果如何? jsp和servlet有什么关系? jsp一般被用在view层 ...

  5. servlet开发(二)之servlet的线程安全问题

    之所以考虑线程安全问题,是因为引入了多线程.多线程指的是这个程序(一个进程)运行时产生了不止一个线程.如果不考虑多线程的话,程序执行只有一条路径,就像人在敲代码的时候只能敲代码,不能戴上耳机听歌.引入 ...

  6. servlet与线程与jdbc connection的关系

    servlet与线程与jdbc connection的关系 都是一一绑定的关系, servlet接受那么多此请求. 一个请求,对应一个线程,对应一个DB POOL的connection. 因为conn ...

  7. Java面试题:Servlet是线程安全的吗?

    Servlet不是线程安全的. 要解释为什么Servlet为什么不是线程安全的,需要了解Servlet容器(即Tomcat)使如何响应HTTP请求的. 当Tomcat接收到Client的HTTP请求时 ...

  8. servlet 最大线程数探索笔记

    servlet默认是单例模式的,所以是单例多线程的.如果实现了singleservlet是可以多个servlet实例,下面是一个servlet的请求生命周期 1 客户端请求该 Servlet:加载 S ...

  9. Servlet的线程是不是共享同一个requset对象及servlet多线程

    servlet多线程   一,servlet容器如何同时处理多个请求. Servlet采用多线程来处理多个请求同时访问,Servelet容器维护了一个线程池来服务请求.线程池实际上是等待执行代码的一组 ...

随机推荐

  1. 反射实现 Data To Model

    调用 : public ActionResult Index() { DataTable dt = new DataTable(); dt.Columns.Add("Name"); ...

  2. webpack快速掌握教程

    转载http://yijiebuyi.com/blog/46fb97b11fb8f4055e0b04d1cecb1f69.html #为什么用webpack 如果我们 前端 javascript 能像 ...

  3. 老李分享:Android性能优化之内存泄漏3

    线程造成的内存泄漏 对于线程造成的内存泄漏,也是平时比较常见的,如下这两个示例可能每个人都这样写过: //——————test1 new AsyncTask<Void, Void, Void&g ...

  4. 关于for()循环使用过程中遇到的问题(俄罗斯方块游戏中遇到的问题)

    for循环的定义: for(参数1:参数2:参数3),参数1通常是初始化参数的,参数2是判断,参数3是对参数的操作.这三个参数都不是必须的. 这里想说的是,参数1的使用:比如下列语 int nLine ...

  5. 美团点评DBProxy读写分离使用说明

    目的 因为业务架构上需要实现读写分离,刚好前段时间美团点评开源了在360Atlas基础上开发的读写分离中间件DBProxy,关于其介绍在官方文档已经有很详细的说明了,其特性主要有:读写分离.负载均衡. ...

  6. JS关于全局变量跟局部变量的总结

    一.Javascript的变量的scope是根据方法块来划分的(也就是说以function的一对大括号{ }来划分).切记,是function块,而for.while.if块并不是作用域的划分标准,可 ...

  7. 前馈神经网络-反向传播(Back Propagation)公式推导走读

        构造:输入神经元个数等于输入向量维度,输出神经元个数等于输出向量维度.(x1=(1,2,3),则需要三个输入神经元)   一 前向后传播   隐层:

  8. [USACO11NOV]牛的障碍Cow Steeplechase

    洛谷传送门 题目描述: 给出N平行于坐标轴的线段,要你选出尽量多的线段使得这些线段两两没有交点(顶点也算),横的与横的,竖的与竖的线段之间保证没有交点,输出最多能选出多少条线段. 因为横的与横的,竖的 ...

  9. fir.im Weekly - 如何在 iOS 上构建 TensorFlow 应用

    本期 fir.im Weekly 收集了最近新鲜出炉的 iOS /Android 技术分享,包括 iOS 系统开发 TensorFlow 教程.iOS 新架构.iOS Notifications 推送 ...

  10. IOS 私有变量 私有属性的书写方法

    一.早期只能定义在.h文件中.用@private 关键字来定义私有变量. @interface ViewController{ @private Bool _isBool; } @end 二.允许在. ...