问题:使用以下的代码演示servlet的线程安全问题?
1 public class MultiThreadQuestion extends HttpServlet { 2 public int count = 0; 3 public void doGet(HttpServletRequest request, HttpServletResponse response) 4 throws ServletException, IOException { 5 // 1. 验证服务器是以线程的方式处理用户请求的 6 try { 7 this.count++; 8 Thread.sleep(5 * 1000); 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 } 12 response.getOutputStream().write(("线程名:"+Thread.currentThread().getName()+"count="+this. count).getBytes()); 13 } 14 }
同时访问以上的代码发现三次同时出现3,这就是线程的并发访问的问题。
解决方案就是:同步
给访问共享资源的代码加锁。
1 public class MultiThreadQuestion extends HttpServlet { 2 public int count = 0; 3 public void doGet(HttpServletRequest request, HttpServletResponse response) 4 throws ServletException, IOException { 5 // 1. 验证服务器是以线程的方式处理用户请求的 6 synchronized (this) { 7 try { 8 this.count++; 9 Thread.sleep(5 * 1000); 10 } catch (InterruptedException e) { 11 e.printStackTrace(); 12 } 13 response.getOutputStream().write(("线程名:"+Thread.currentThread().getName()+"count="+this.count).getBytes()); 14 } 15 } 16 }
总结:
1.如果直接使用同步关键字,那么会导致servlet的运行效率严重的降低。
2.尽量避免使用servlet的成员变量。
3.如果避免不了那么我们就需要使用线程安全的成员变量。
ArrayList Vector HashSet
如果需要不是线程安全的集合可以使用Collections进行线程安全的转换
4.ServletContext、HttpSession需要使用的时候一定要使用同步。
5.在servlet中最好使用局部变量。