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 @   QiaoZhi  阅读(273)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示