servlet线程不安全

1.servlet是线程不安全的

局部变量不存在线程安全问题,比如:

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        int i = 0;
        i++;
        try {
            java.lang.Thread.sleep(1000*10);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        response.getWriter().write(i+"");
    }

 

  结果:两次访问上面的servlet输出均为1

 

 

 

比如下面代码存在线程安全问题:(全局变量)

 

 结果:

   第一次访问本该输出1,第二次输出2,可是第一次执行完后没有输出i被第二次访问的修改。

2. 解决办法1:

synchronized同步代码块      (方法执行独占该锁,也就是这个线程执行完其他线程才能执行,一个线程访问其他线程不能访问)

public class Thread extends HttpServlet {

    int i = 0;

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        synchronized (this) {
            i++;
            try {
                java.lang.Thread.sleep(1000 * 10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            response.getWriter().write(i + "");
        }
    }

 

结果:

  访问3次输出1,2,3

 

3.解决办法2

  实现SingleThreadModel接口(一个空接口,Serializable也是一个空接口(序列化接口),Cloneable接口也是一个空接口(克隆接口)),空接口也被称为标记接口

public class Thread extends HttpServlet implements SingleThreadModel,Serializable,Cloneable {

    int i = 0;

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
            i++;
            try {
                java.lang.Thread.sleep(1000 * 10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            response.getWriter().write(i + "");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

 

  这个访问两次输出1,1.上面的接口解决办法是一个线程创建一个servlet,因此是线程安全的,且每次都输出1.

  注意:子类在覆盖父类的方法时,不能抛出比父类更多的异常(儿子不能比父亲干更多的坏事),所以只能捕捉异常,通常在web层捕获异常,给用户一个友好提示。

 

posted @ 2017-08-26 22:08  QiaoZhi  阅读(269)  评论(0编辑  收藏  举报