博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
IT兄弟连 JavaWeb教程 Servlet线程安全问题
阅读量:5789 次
发布时间:2019-06-18

本文共 2396 字,大约阅读时间需要 7 分钟。

hot3.png

在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接口。

转载于:https://my.oschina.net/u/4125915/blog/3047832

你可能感兴趣的文章
利用rand7()构造rand10()
查看>>
MySQL 备份与恢复
查看>>
吃午饭前,按书上的代码写会儿--Hunt the Wumpus第一个版本
查看>>
easyui中combobox的值改变onchang事件
查看>>
Eclipse魔法堂:任务管理器
查看>>
一周自学动态站点设计
查看>>
Android-Universal-Image-Loader
查看>>
Android 从硬件到应用:一步一步向上爬 4 -- 使用 JNI 方法调硬件驱动
查看>>
TEST
查看>>
loadrunner 的Administration Page里面设置
查看>>
程序员喜欢怎样的职位描述?(转)
查看>>
威胁快报|ProtonMiner挖矿蠕虫扩大攻击面,加速传播
查看>>
PAT A1116
查看>>
App上架/更新怕被拒? iOS过审“避雷秘籍”请查收
查看>>
CentOS 7 防火墙操作
查看>>
关于 top 工具的 6 个替代方案
查看>>
程序员最讨厌的9句话,你可有补充?
查看>>
PAT A1037
查看>>
浅谈RPC
查看>>
HDU 4422 The Little Girl who Picks Mushrooms(简单题)
查看>>