Servlet基础(三) Servlet的多线程同步问题
Servlet基础(三) Servlet的多线程同步问题
Servlet/JSP技术和ASP、PHP等相比,由于其多线程运行而具有很高的执行效率。
由于Servlet/JSP默认是以多线程模式执行的,所以,在编写代码时需要非常细致地考虑多线程的同步问题。
如果在编写Servlet/JSP程序时不注意到多线程的同步问题,这往往造成程序在少量用户访问时没有任何问题,而在并发用户上升到一定值时,就会经常出现一些莫名其妙的问题,对于这类随机性的问题调试难度也很大。
比如下面这个程序就有问题。
存在多线程问题的程序例子
这个例子中,首先有一个JSP页面,其中有一个简单的表单:
<form action="MultiThreadServlet">
<input type="text" name="username">
<input type="submit" value="submit">
</form>
提交表单后,转向一个Servlet进行处理:
获取请求中的参数,并且调用setAttribute方法将其值存储,转向下一个jsp页面:
package com.shengqishiwind.servlet; import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class MultiThreadServlet extends HttpServlet
{
//使用成员变量
private String username; public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
//从请求中得到参数,即用户名
username = request.getParameter("username"); //得到当前线程的名字
System.out.println("Thread Name: " + Thread.currentThread().getName()); //模拟一些后端的业务处理
try
{ Thread.sleep(10000);
}
catch (Exception e)
{
e.printStackTrace();
} request.setAttribute("username", username);
//请求转发
request.getRequestDispatcher("hello.jsp").forward(request, response); } }
中间让线程停留了10秒钟,来模拟一些操作。
在下一个JSP页面中将该值显示出来:
<body>
username: <%= request.getAttribute("username")%>
</body>
这样做有什么问题呢?
打开浏览器,输入访问地址后,输入一个用户名zhangsan,再打开一个窗口,输入用户名lisi。
两个浏览器窗口都提交以后,过了一定时间,可以看到两边返回值都是lisi。
问题原因
Servlet的多线程同步问题:
Servlet本身是单实例的,这样当有多个用户同时访问某个Servlet时,会访问该唯一的Servlet实例中的成员变量,如果对成员变量进行写入操作,那就会导致Servlet的多线程问题,即数据不一致。
解决同步问题的方案
1.解决Servlet多线程同步问题的最好方式:
去除实例变量,使用局部变量。
比如上面那个例子修改如下:
public class MultiThreadServlet extends HttpServlet
{
//使用成员变量
//private String username; public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
//从请求中得到参数,即用户名
String username = request.getParameter("username"); //得到当前线程的名字
System.out.println("Thread Name: " + Thread.currentThread().getName()); //模拟一些后端的业务处理
try
{ Thread.sleep(10000);
}
catch (Exception e)
{
e.printStackTrace();
} request.setAttribute("username", username);
//请求转发
request.getRequestDispatcher("hello.jsp").forward(request, response); } }
不使用成员变量,而使用局部变量,因为局部变量在每个线程中都有各自的实例。
所以对Servlet来说,如果要对某个变量做写入操作,一定不要使用成员变量,而要使用局部变量。
2.使用同步代码块
synchronized{}
3.Servlet实现javax.serlvet.SingleThreadModel(Servlet2.4中已经废弃了该接口),此时Servlet容器将保证Servlet实例以单线程方式运行,也就是说,同一时刻,只会有一个线程执行Servlet的service()方法。
(这种方式了解一下就行了)。
参考资料
圣思园张龙老师Java Web视频教程。
Servlet基础(三) Servlet的多线程同步问题的更多相关文章
- Java第三阶段学习(十一、Servlet基础、servlet中的方法、servlet的配置、ServletContext对象)
一.Servlet简介 1.什么是servlet: sun公司提供的一套规范(接口),用来处理客户端请求.响应给浏览器的动态资源.但servlet的实质就是java代码,通过java的API动态的向 ...
- servlet多线程同步问题
Servlet/JSP技术和ASP.PHP等相比,由于其多线程运行而具有很高的执行效率.•由于Servlet/JSP默认是以多线程模式执行的,所以,在编写代码时需要非常细致地考虑多线程的同步问题.•如 ...
- 2 Servlet基础
作者:禅楼望月(http://www.cnblogs.com/yaoyinglong) 1. 从浏览器访问Servlet的流程 刚才发现,这里的图片不能正常显示,所以我给个链接,大家可以下载下来看从浏 ...
- Java之JSP和Servlet基础知识
JSP基础 JSP起源 JSP,JavaServer Pager的简称.由SUN倡导并联合其它公司创建. JSP是一门脚本语言 JSP可以嵌入到HTML中 JSP拥有Java语言的所有特性 面向对象. ...
- J2EE基础之Servlet
J2EE基础之Servlet 1. 什么是Servlet? Servlet即Java服务小程序,是使用应用程序设计接口以及相关类和方法的Java程序.它可以作为一种插件,像Applet程序一样嵌入到 ...
- JSP数据交互(二)和Servlet基础
01.Application原理与应用 01.application对象的作用域范围是整个应用服务,而它在应用中所承担的责任就类似于一个全局变量.只要服务启动,则application对象就会存在. ...
- Servlet基础(一) Servlet简介 关键API介绍及结合源码讲解
Servlet基础(一) Servlet基础和关键的API介绍 Servlet简介 Java Servlet是和平台无关的服务器端组件,它运行在Servlet容器中. Servlet容器负责Servl ...
- JavaWeb学习之Servlet(三)----Servlet的映射匹配问题、线程安全问题
[声明] 欢迎转载,但请保留文章原始出处→_→ 文章来源:http://www.cnblogs.com/smyhvae/p/4140529.html 一.Servlet映射匹配问题: 在第一篇文章中的 ...
- JSP/Servlet基础语法
相关学习资料 http://my.oschina.net/chape/blog/170247 http://docs.oracle.com/cd/E13222_01/wls/docs81/webapp ...
随机推荐
- SQLServer学习笔记系列4
一.写在前面的话 好多天没有记录sql学习笔记了,要坚持下去,坚信每一点的进步都是为在积蓄力量.今天看到一幅图,特此分享出来. 通过这幅图,我看到的是每人站在自己的角度看问题,感受是不一样的,就如同学 ...
- 转载:java程序员如何拿到2万月薪
作者:匿名用户链接:https://www.zhihu.com/question/39890405/answer/83676977来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...
- SQL Server代理(7/12):作业活动监视器
SQL Server代理是所有实时数据库的核心.代理有很多不明显的用法,因此系统的知识,对于开发人员还是DBA都是有用的.这系列文章会通俗介绍它的很多用法. 在这个系列的前几篇文章里,你创建配置了SQ ...
- 原生js实现简洁的返回顶部组件
本文内容相当简单,所以没有发布到博客园首页,如果你不幸看到,那只能是我这篇文章的荣幸,谢谢你的大驾光临~(本博客返回顶部的功能就使用的是这个组件) 返回顶部组件是一种极其常见的网页功能,需求简单:页面 ...
- 根据日期查询access数据库
获取指定日期的记录 1.select Field1 from A where format("yyyy-MM-dd",Field1)=#2011-10-07# 有时不能获取记录 ...
- Response.Redirect 无法跳转页面
错误现象:Response.Redirect(Server.MapPath("BackIndex.aspx")); 打断点测试执行了这一句,Server.MapPath(" ...
- Ajax实现定时刷新页面
function deleteValue(){ var refresh = function() { $.ajax({ type:'post', url:'/Application/index ...
- ASP.NET MVC 请求流程
一.应用程序启动 1.Application_Start方法,程序启动 2.RegisterRoutes方法,注册路由 3.System.Web.Mvc.RouteCollectionExtensio ...
- MVC - Action和ActionResult
Action 定义在Controller中的Action方法返回ActionResult对象,ActionResult是对Action执行结果的封装,用于最终对请求进行响应.HTTP是一个单纯的采用请 ...
- dapper 注意事项之GUID
今天把ef框架换成了dapper,数据库使用的是mysql. 主键使用GUID,mysql数据库中设置的为varchar(36). 使用dapper报错,不能将string转换为GUID,后来调试比对 ...