Servlet线程安全
概述
在探讨java线程安全前,让我们先简要介绍一下Java语言。
任何语言,如C++,C#,Java,它们都有相通之处,特别是语法,但如果有人问你,Java语言的核心是什么?类库?关键字?语法?似乎都不 是。Java语言的核心,也就是Sun始终不愿意开源的东西:Java虚拟机的实现(不过sun公开了其Java虚拟机规范),也就有了BEA的 JRockit,IBM的Jikes,Sun的Hotspot。
Java的核心有两点,Java类加载(Java Class Loader)和Java内存管理,它们具体体现在Java类库的以下几个类:
java.lang.ClassLoader(java.lang.Class):我们调用的类,包括其接口和超类,import的类是怎么被Java虚拟机载入的?为什么static的字段在servlet容器里面可以一直生存下去(Spring容器中)?
java.lang.Thread(java.lang.ThreadLocal):垃圾回收是怎么进行的(垃圾回收线程)?我们的程序是怎么退出的?
java.lang.refelect.Proxy(java.lang.refelect.Method):为什么Tomcat、 Tapestry、Webwork、Spring等容器和框架可以通过配置文件来调用我们写的类?Servlet规范、JSF规范、EJB规范、JDBC 规范究竟是怎么回事?为什么它们几乎都是一些接口,而不是具体类?
Servlet线程安全
在Java的server side开发过程中,线程安全(Thread Safe)是一个尤为突出的问题。因为容器,如Servlet、EJB等一般都是多线程运行的。虽然在开发过程中,我们一般不考虑这些问题,但诊断问题 (Robust),程序优化(Performance),我们必须深入它们。
什么是线程安全?
在Java里,线程安全一般体现在两个方面:
1、多个thread对同一个java实例的访问(read和modify)不会相互干扰,它主要体现在关键字synchronized。如 ArrayList和Vector,HashMap和Hashtable(后者每个方法前都有synchronized关键字)。如果你在 interator一个List对象时,其它线程remove一个element,问题就出现了。
2、每个线程都有自己的字段,而不会在多个线程之间共享。它主要体现在java.lang.ThreadLocal类,而没有Java关键字支持,如像static、transient那样。
一个普遍的疑问,我们的Servlet中能够像JavaBean那样declare instance或static字段吗?如果不可以?会引发什么问题?
答案是:不可以。下面以实例讲解:
首先,写一个普通的Servlet,里面有instance字段count:
web.xml >>
<servlet><servlet-name>SimpleServlet</servlet-name><servlet-class>servlet.SimpleServlet</servlet-class> </servlet> <servlet-mapping><servlet-name>SimpleServlet</servlet-name><url-pattern>/SimpleServlet</url-pattern> </servlet-mapping>
SimpleServlet >>
public class SimpleServlet extendsHttpServlet {private int counter = 0; @Overrideprotected voidservice(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {response.getWriter().println("<HTML><BODY>");response.getWriter().println(this + " ==> ");response.getWriter().println(Thread.currentThread()+ ": <br>");for(int c=0;c<10;c++){response.getWriter().println("Counter = " + counter + "");try{Thread.sleep(1000); counter++; }catch(Exception e) {e.printStackTrace();}}response.getWriter().println("</BODY></HTML>");}}
test.html >>
<html> <body> <table> <tr> <td><iframesrc="SimpleServlet"name="servlet1"height="200%"> </iframe></td> </tr> </table> </body> </html>
test.html的内容如上所示,打开3个IE浏览器,同时在浏览器中输入:
a: http://localhost:8080/ServletTest/SimpleServlet b: http://localhost:8080/ServletTest/SimpleServlet c: http://localhost:8080/ServletTest/SimpleServlet
测试结果如下:
我们会发现三点:
1、Servlet是一个单例对象(Singleton),因为我们看到多次请求的this指针所有打印出来的hashCode值都相同。
2、servlet在不同的线程(线程池)中运行,如http-8080-1,http-8080-2,http-8080-3 等输出值可以明显区分出不同的线程执行了不同一段Servlet逻辑代码。
3、count变量在不同的线程中共享,而且它的值被不同的线程修改,输出时已经不是顺序输出。也就是说,其他的线程会篡改当前线程中实例变量的值,针对这些对象的访问不是线程安全的。
上面的结果,违反了线程安全的两个方面。
那么,我们怎样保证按照我们期望的结果运行呢?首先,我想保证产生的count都是顺序执行的。
我们将Servlet代码重构如下:
public class SimpleServlet extendsHttpServlet {private int counter = 0;private String mutex = ""; @Overrideprotected voidservice(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {response.getWriter().println("<HTML><BODY>");response.getWriter().println(this + " ==> ");response.getWriter().println(Thread.currentThread()+ ": <br>");synchronized(mutex){for(int c=0;c<10;c++){response.getWriter().println("Counter = " + counter + "<BR>");try{Thread.sleep(1000); counter++; }catch(Exception e) {e.printStackTrace();}}}response.getWriter().println("</BODY></HTML>");}}
这符合要求,输出都是按顺序的,这正式synchronized的含义。
附带说一下,我现在synchronized的是一个字符串变量mutex,不是this对象,这主要是从performance和 Scalability考虑。Synchronized用在this对象上,会带来严重的可伸缩性的问题(Scalability),所有的并发请求都要排队!
转载:http://www.cnblogs.com/gw811/archive/2012/09/07/2675294.html
转载于:https://www.cnblogs.com/go-skill/p/6078082.html
Servlet线程安全相关推荐
- 深入研究Servlet线程安全性问题
摘 要:介绍了Servlet多线程机制,通过一个实例并结合Java 的内存模型说明引起Servlet线程不安全的原因,给出了保证Servlet线程安全的三种解决方案,并说明三种方案在实际开发中的取舍. ...
- Servlet功能实现和执行过程、servlet的生命周期、Servlet线程安全问题、Servlet的三种映射方式、ServletConfig、ServletContext
1. 什么是Servlet? Servlet是SUN公司提供的一套规范,名称就叫Servlet规范,它也是JavaEE规范之一. 第一:Servlet是一个运行在web服务端的java小程序 第二:它 ...
- Servlet线程安全2
为什么80%的码农都做不了架构师?>>> Servlet的多线程机制 Servlet体系结构是建立在Java多线程机制之上的,它的生命周期是由Web容器负责的.当客户端第一次请 ...
- IT兄弟连 JavaWeb教程 Servlet线程安全问题
2019独角兽企业重金招聘Python工程师标准>>> 在Internet中,一个Web应用可能被来自西面八方的客户并发访问(即同时访问),而且有可能这些客户并发访问的是Web应用中 ...
- tomcat servlet 线程
在服务器里,有一个servlet,当客户端第一次访问服务器时,tomcat会 帮我们建一个servlet的对象出来,(注意: tomcat里面可能部署了10个Servlet,如果某一个Servlet从 ...
- java servlet 多线程_Servlet的多线程和线程安全
线程安全 首先说明一下对线程安全的讨论,哪种情况我们可以称作线程安全? 网上对线程安全有很多描述,我比较喜欢<Java并发编程实战>给出的定义,"当多个线程访问某个类时,不管运行 ...
- servlet单实例多线程 ---线程安全问题是由实例变量造成的,只要在Servlet里面的任何方法里面都不使用实例变量,那么该Servlet就是线程安全的。(所有建议不要在servlet中定义成员变
Servlet 单例多线程 Servlet如何处理多个请求访问? Servlet容器默认是采用单实例多线程的方式处理多个请求的: 1.当web服务器启动的时候(或客户端发送请求到服务器时),Servl ...
- javaweb学习总结二十三(servlet开发之线程安全问题)
一:servlet线程安全问题发生的条件 如果多个客户端访问同一个servlet时,发生线程安全问题,那么它们访问的是相同的资源.如果访问 的不是相同资源,则不存在线程安全问题. 实例1:不会产生线程 ...
- 关于java Servlet,Struts,springMVC 的线程安全问题
2019独角兽企业重金招聘Python工程师标准>>> 现在主流的java的前端框架有:struts1,struts2,springmvc 还有最根本的servlet; 前些天一个朋 ...
最新文章
- Java源码详解四:String源码分析--openjdk java 11源码
- JavaScript使用技巧精萃
- python 引用(import)文件夹下的py文件的方法
- 【HoorayOS】开源的Web桌面应用框架(第二版 v120311)
- 上传文件Base64格式(React)
- 【证明】【一题多解】【等价转换】—— 排列组合的计算
- 下行文格式图片_通知的格式及范文图片_通知格式 通知的格式及范文
- 全国各省份简称、省会、经纬度
- 自然语言处理的会议、论文集下载
- 【classic】MMD镜头+动作打包下载.zip
- 2.1 Apache Hadoop、HDFS - Apache Hadoop概述
- FDD LTE B1是什么
- 小白通过JDBC在AndroidStudio一步步来访问MYSQL数据库
- python大一期末考试_python期末考试复习试卷
- 微信公众号文章链接正则校验
- Ctrl+win+d win的虚拟桌面如何撤销
- linux ide sata硬盘,Linux 下SATA与IDE硬盘区别
- 最全的 cadence 元器件库详细说明
- 最新虚拟商品自动发货系统源码 v1.1.1 (发货100)
- 计算机老师副业能做什么,教师除了本职工作,还能做哪些副业?