标签:容器 request 实例变量 只读 i++ amp 方法 code 除了
1、多线程Servlet模型--单实例多线程的模式
默认情况下servlet对声明的servlet,只创建一个servlet实例,多个客户访问这个servlet那么servlet容器采取多线程方式。
多个客户同事请求同一个servlet,那么会有多个线程同时执行这个servlet实例的service方法,servlet容器采取的就是单实例多线程的模式,节省了servlet实例的创建,但是引发的并发问题。
2、servlet的线程安全
2.1变量的线程安全
2.1.1避免全局变量
1 public class HelloWorldServlet extends HttpServlet{ 2 private String userName; 3 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException 4 { 5 userName=request.getParameter("userName"); 6 PrintWriter out=response.getWriter(); 7 if(userName!=null&&userName!="") 8 { 9 out.print(userName); 10 } 11 else { 12 out.println("用户名不存在"); 13 } 14 } 15 }
上面的userName为全局变量,多线程调用时会有问题,将变量生命正在方法内(局部变量),每个线程执行方法时重新实例化userName,这样就不会有问题了。
如果是静态资源可以添加final修饰,表示不可变
2.2属性的安全
servlet中可以访问保存在servletContent,httpSession,ServletRequest对象中的属性,这三种对象都提供了getAttribute(),setAttribute()方法用来设置获取属性值,那么这三个对象是否是线程安全?
2.2.1servletContent
首先servletContent是被应用程序下所有的servlet共享的,多个servlet对servletContent同时进行设置和访问,就会出现线程并发问题。
//代码一 1 protected void service(HttpServletRequest request, HttpServletResponse response) 2 { 3 String userName=request.getParameter("userName"); 4 if ("login") { 5 List list=(List)getServletContext().getAttribute("userList"); 6 list.add(userName); 7 } 8 else { 9 List list=(List)getServletContext().getAttribute("userList"); 10 list.remove(userName); 11 } 12 } //代码二 1 protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException 2 { 3 List list=(List)getServletContext().getAttribute("userList"); 4 int count=list.size(); 5 for(int i=0;i<count;i++) 6 { 7 PrintWriter out=response.getWriter(); 8 out.println(list.get(i)); 9 } 10 }
两个请求并发,当线程一执行到代码二第5行时,此时count=5,但是线程二此时执行代码一第10行,删除了一个数据,当线程一再执行就会出现数组越界的问题,怎么解决此类问题呢,第一就是把servletContent拷贝保存起来,第二种就是使用synchronized进行同步(效率低)
2.2.2 httpSession
httpSession是在用户会话中存在的,不像ServletContent是所有的用户共享的,所有说一个httpSession同一时刻只能有同一个用户进行请求,理论上看起来是线程安全的,其实并不是,这和浏览器有关系,同一个浏览器只能具有一个session,如果同一个用户在两个浏览器窗口同时请求,同样会出现线程安全的问题。
2.2.3httpRequest
httpRequest是线程安全的,应为每个线程都会调用service,都会创建一个新的httpRequest,和局部变量一样。
标签:容器 request 实例变量 只读 i++ amp 方法 code 除了
原文地址:https://www.cnblogs.com/zhang19925/p/12253983.html