Servlet线程不安全问题及解决办法
2018-02-05 10:23
309 查看
Servlet安全性问题
当用户发送Http请求的时候,tomcat会读取web.xml中的内容,加载所定义的Servlet并实例化该Servlet.Servlet只实例化一次,tomcat中Servlet是单例的.同一个Servlet可以同时处理多个用户请求,比如同时有两个用户A和用户B登录时,会启动两个负责登录的Servlet线程,并且触发Service方法才处理请求.所以在Servlet处理共享数据的时候,会出现线程安全问题.举例
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(name = "ThreadServlet", urlPatterns = {"/ThreadServlet"}) public class ThreadServlet extends HttpServlet { //共享数据 private int count=0; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); String threadName = Thread.currentThread().getName(); for (int i = 0; i < 1000; i++) { System.out.println(threadName+" Count:"+count); try { Thread.sleep(100); count ++; } catch (InterruptedException e) { e.printStackTrace(); } } } }
部分输出:
http-nio-8080-exec-5 Count:5027 http-nio-8080-exec-4 Count:5028 http-nio-8080-exec-7 Count:5029 http-nio-8080-exec-3 Count:5030 http-nio-8080-exec-6 Count:5032 http-nio-8080-exec-8 Count:5032 http-nio-8080-exec-5 Count:5033
可以看出,出现了数据错误.
解决办法
尽量使用局部变量使用全局变量会出现线程安全问题,所以我们可以尽量使用局部变量.在Servlet中,负责保存上下文ServletContext和负责处理Session对象的HttpSession是线程不安全的,而负责处理请求的ServletRequest是线程安全的.
加锁
用synchronized进行保护,但是要尽量的缩小保护范围.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); String threadName = Thread.currentThread().getName(); synchronized (this){ for (int i = 0; i < 1000; i++) { System.out.println(threadName+" Count:"+count); try { Thread.sleep(100); count ++; } catch (InterruptedException e) { e.printStackTrace(); } } } }
ThreadLocal
ThreadLocal为每一个线程提供一个变量副本,线程之前该变量是独立的.可以通过ThreadLocal解决Servlet单例线程不安全问题.
package com.liushiyao.servlet.thread; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /* 使用ThreadLocal的解决Servlet线程安全问题 Servlet:单例多线程,线程不安全 ThreadLocal:为每个线程复制一个变量副本,线程之间数据不共享 */ @WebServlet(name = "ThreadLocalLocalServlet",urlPatterns = "/ThreadLocalServlet") public class ThreadLocalServlet extends HttpServlet{ //使用ThreadLocal,为每个线程创建一个变量副本 private ThreadLocal threadLocal = new ThreadLocal(){ @Override protected Object initialValue() { return new Integer(0); } }; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); String threadName = Thread.currentThread().getName(); for (int i = 0; i < 1000; i++) { System.out.println(threadName+" Count:"+threadLocal.get()); try { Thread.sleep(100); int count = ((Integer)(threadLocal.get())).intValue(); count ++; threadLocal.set(count); } catch (InterruptedException e) { e.printStackTrace(); } } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
相关文章推荐
- 玩转Web之servlet(五)---- 怎样解决servlet的线程安全问题
- 玩转Web之servlet(五)---- 怎样解决servlet的线程安全问题
- 线程安全问题及解决办法
- Servlet模拟网上售票问题,解决线程的安全问题
- java线程的同步安全问题三种解决办法
- Spark程序执行过程中遇到的线程安全问题及解决办法
- 玩转Web之servlet(五)---- 怎样解决servlet的线程安全问题
- 关于单实例多线程的servlet的线程安全问题的探讨
- C#技巧【调用线程无法访问此对象,因为另一个线程拥有该对象的问题的解决办法】【C#读写EXCEL源码提示“office检测到此文件存在一个问题。为帮助保护您的计算机,不能打开此文件”的解决】
- linux 线程操作问题undefined reference to 'pthread_create'的解决办法(cmake)
- 在Eclipse中编写servlet时出现"The import javax.servlet cannot be resolved" 问题解决办法
- 多线程安全问题及解决办法
- Servlet 的线程安全问题分析
- ASP.NET 4.0中使用FCKeditor遇到安全问题警告的解决办法
- ASP.NET 4.0中使用FreeTextBox和FCKeditor遇到安全问题警告的解决办法
- Servlet的线程安全问题
- 本地运行swf访问网络的安全问题解决办法
- Servlet接收JSP参数乱码问题解决办法(转)
- Oracle 11g EM安全证书问题无法访问的解决办法
- Servlet实现下载 firefox下文件名有空格时,文件名会被截断 问题解决办法