在Internet中,一个Web应用可能被来自西面八方的客户并发访问(即同时访问),而且有可能这些客户并发访问的是Web应用中的同一个Servlet,Servlet容器为了保证能同时相应多个客户端要求访问的同一个Servlet的HTTP请求,通常会为每个请求分配一个工作线程,这些工作线程并发执行同一个Servlet对象的service()方法。

当多个线程并发执行同一个Servlet对象的service()方法时,可能会导致并发问题。

例:下面的案例用于演示导致并发问题的情形。

public class HelloServlet extends HttpServlet{

public void service(HttpServletRequest request,

HttpServletResponse response)throws ServletException,IOException{

private String username = null;

username = request.getParameter("username");

if(username != null){

username = new String(username.getBytes("ISO-8859-1"),"utf-8");

}

try{

Thread.sleep(3000);

}catch(Exception e){

e.printStackTrace();

}

response.setContentType("text/html;charset=utf-8");

PrintWriter out = response.getWriter();

out.println("您好:" + username);

out.close();

}

}

在HelloServlet中有一个实例变量username,在HelloServlet的service()方法中,先将username请求参数赋值给实例变量username,最后再向客户端返回实例变量username的值,为了延长响应客户请求的时间,在service()方法中调用Thread.sleep(3000)方法睡眠3秒。

在web.xml文件中为HelloServlet映射的URL为"/hello"。同时打开两个浏览器,分别输入如下URL:

http://localhost:8080/helloapp/hello?username=老鼠

http://localhost:8080/helloapp/hello?username=小鸭

以上两个浏览器并发访问HelloServlet,出现了奇怪的现象。在第一个浏览器中,虽然客户端提供的请求参数username的值为"老鼠",HelloServlet却返回"您好:小鸭"。为什么一眨眼,老鼠就变成了鸭呢?

下面在看另一个案例:

public class AdderServlet extends HttpServlet{

public void service(HttpServletRequest request,

HttpServletResponse response)throws ServletException,IOException{

private int sum = 100;

int increase = Integer.parseInt(request.getParameter("increase"));

response.setContentType("text/html;charset=UTF-8");

PrintWriter out = response.getWriter();

out.println(sum + "+" + increase + "=");

try{

Thread.sleep(3000);

}catch(Exception e){

e.printStackTrace();

}

sum+=increase;

out.println("sum");

out.close();

}

}

在AdderServlet中有一个实例变量sum,在AdderServlet的service()方法中提取increase请求参数,再把实例变量sum加上increase,最后再向客户端返回实例变量sum的值。为了延长响应客户请求的时间,在service()方法中调用Thread.sleep(3000)方法睡眠3秒钟。

在web.xml文件中为AdderServlet映射的URL为"/adder"。同时打开两个浏览器,分别输入如下URL:

http://localhost:8080/helloapp/adder?increase=100

http://localhost:8080/helloapp/adder?increase=200

两个浏览器并发访问AdderServlet,出现了奇怪的现象。在第二个浏览器中,客户端提供的请求参数increase的值为"200",AdderServlet返回"100+200=400",AdderServlet所做的加法运算显然是错误的。

在解决并发问题时,主要遵循以下原则:

●  根据实际应用需求,合理决定在Servlet中定义的变量的作用于。变量到底为实例变量,还是局部变量,是由实际应用需求决定的。

●  对于多个线程同时访问共享数据而导致并发问题的情况,使用Java同步机制对线程进行同步。

●  不提倡使用被废弃的javax.servlet.SingleThreadModel接口。

IT兄弟连 JavaWeb教程 Servlet线程安全问题的更多相关文章

  1. IT兄弟连 JavaWeb教程 Servlet表单数据

    很多情况下,需要传递一些信息,从浏览器到Web服务器,最终到后台程序.浏览器使用两种方法可将这些信息传递到Web服务器,分别为GET方法和POST方法. 1.GET方法 GET 方法向页面请求发送已编 ...

  2. IT兄弟连 JavaWeb教程 Servlet API

    Java Servlet是运行在带有支持Java Servlet规范的解释器的web服务器上的Java类. Servlet可以使用javax.servlet和javax.servlet.http包创建 ...

  3. IT兄弟连 JavaWeb教程 Servlet会话跟踪 经典案例

    案例需求:编写一个servlet,可以向session中存放一个消息,再编写一个servlet可以从session取得session中存放的这个消息. 案例实现: package com.xdl.se ...

  4. IT兄弟连 JavaWeb教程 Servlet会话跟踪 Session常用方法

    ●  public Object getAttribute(String name) 该方法返回在该session会话中具有指定名称的对象,如果没有指定名称的对象,则返回null. ●  public ...

  5. IT兄弟连 JavaWeb教程 Servlet会话跟踪 Session技术

    Servlet提供了HttpSession接口,该接口提供了一种跨多个页面请求或访问网站时识别用户以及存储有关用户信息的方式. Servlet容器使用这个接口来创建一个HTTP客户端和HTTP服务器之 ...

  6. IT兄弟连 JavaWeb教程 Servlet会话跟踪 Cookie常用方法

    以下是在Servlet中操作Cookie时可使用的有用的方法列表 ●  public void setDomain(String pattern) 该方法设置cookie适用的域,例如 itxdl.c ...

  7. IT兄弟连 JavaWeb教程 Servlet会话跟踪 Cookie路径问题

    操作Cookie时,需要注意路径问题: 设置操作:任何路径都可以设置Cookie,但是有时我们也是用设置进行替换Cookie和删除Cookie(maxAge=0)! 替换:只能由完全相同的路径来操作! ...

  8. IT兄弟连 JavaWeb教程 Servlet会话跟踪 创建Cookie

    Tomcat作为Web服务器,对Cookie提供了良好的支持.那么,运行在Tomcat的Servlet该如何访问Cookie呢?幸运的是,Servlet无需直接和HTTP请求或响应中的原始Cookie ...

  9. IT兄弟连 JavaWeb教程 Servlet中定义的变量的作用域类型

    在Java语言中,局部变量和实力变量有着不同的作用于,它们的区别如下: 局部变量在一个方法中定义,每当一个线程执行局部变量所在的方法时,在线程的堆栈中就会创建这个局部变量,当线程执行完该方法,局部变量 ...

随机推荐

  1. Raw-OS源代码分析之消息系统-Queue_Buffer

    分析的内核版本号截止到2014-04-15,基于1.05正式版.blogs会及时跟进最新版本号的内核开发进度,若源代码凝视出现"???"字样,则是未深究理解部分. Raw-OS官方 ...

  2. [java][db]JAVA分布式事务原理及应用

    JTA(Java Transaction API)同意应用程序运行分布式事务处理--在两个或多个网络计算机资源上訪问而且更新数据.JDBC驱动程序的JTA支持极大地增强了数据訪问能力.  本文的目的是 ...

  3. 《Deep Learning》全书已完稿_附全书电子版

    Deep Learning第一篇书籍最终问世了.站点链接: http://www.deeplearningbook.org/ Bengio大神的<Deep Learning>全书电子版在百 ...

  4. UIAutomation使用測试入门

    自己主动化測试的优点: 1.自己主动化能够自己主动測试,不须要人的干预.同一时候还能够不断地反复某一个动作. 2.自己主动化測试在添加了新的功能之后.还能够回归到原理的功能,使其原来的功能不会受到影响 ...

  5. hibernate的查询缓存和二级缓存的配合使用

    我的上一篇博客Hibernate缓存体系之查询缓存(query cache),以及list和iterate方法的差别介绍了查询缓存的概念,以及list和iterate的差别.读者可能注意到:那篇博客測 ...

  6. 64位CentOs7源码安装mysql-5.6.35过程分享

    首先安装依赖包,避免在安装过程中出现问题 [root@bogon liuzhen]# yum -y install gcc gcc-c++[root@bogon liuzhen]# yum -y in ...

  7. Mysql整数运算NULL值处理注意点

    CleverCode近期在导出报表的时候,在整数做减法的时候,发现整数减去null得到是null.这是一个细节问题,希望大家以后注意. 1 表中的数据 total,used都是整形,同意为空. 2 有 ...

  8. Android - 监听Activity点击无效

    监听Activity点击无效 本文地址: http://blog.csdn.net/caroline_wendy Activity须要先在Manifest注冊,才干在app中使用; Manifest: ...

  9. Messaging Patterns for Event-Driven Microservices

    Messaging Patterns for Event-Driven Microservices https://content.pivotal.io/blog/messaging-patterns ...

  10. idea 破解注册方法总结

    注册码(无期限) JetbrainsCrack-2.6.2.jar适用于ideaIU-2017.2.之前版本,若版本较新适用 JetbrainsCrack-2.6.3_proc.jar. 其中Jetb ...