Servlet线程安全问题及解决

问题:

        servlet在访问之后,就会执行实例化操作,创建一个Setvlet对象,而tomcat容器可以同时多个并发访问同一个setvlet,如果在方法中对成员变量进行修改,就会存在线程安全问题

代码演示:

public class SafeServlet extends HttpServlet {
    private String message = "";

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.接收参数
        //2.调用业务逻辑,得到登陆结果
        message = "访问成功";//访问失败
        PrintWriter writer = resp.getWriter();
        writer.println(message);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet( req,resp );
    }
}

简单一点来说,就是如果小李和小王同时访问名为SafeServlet的servlet,当小王因为网络原因或者其他原因卡在了访问失败页面,而小李则访问成功了,此时SafeServlet中成员变量message的值就变为了访问成功,正在此时,小王卡住的原因解决了,此时小王就会发现自己虽然跳到访问成功页面,但是自己不能进行下一步操作。

那怎么样解决servlet线程安全问题呢?

解决线程安全问题有三种方式:

1.synchronized

        将存在线程安全问题的代码放在同步代码开中

2.实现SingleThreadModel接口

        servlet实现SingleThreadModel接口后,每一个线程都会创建一个servlet实例,这样每一个客户就不会存在资源的共享问题,但由于响应太低,已被淘汰

3.尽可能使用局部变量

synchronized:每一个客户进来都会等待上一个客户释放才会进入下一个客户,这样就会导致效率低下,试想一下,如果真的是一个高并发的程序,它的效率会怎样,所以此方式虽然可以解决问题,但是效率十分低下

public class SafeServlet extends HttpServlet {
    private String message = "";

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        synchronized (this) {
            message = "访问成功";//访问失败
            PrintWriter writer = resp.getWriter();
            writer.println( message );
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet( req,resp );
    }
}

实现SingleThreadModel接口:上面已经说了每一个线程都会创建一个servlet实例,每一个对象都会持有独有的一个对象,这样会导致时间、资源的浪费,因此此方式已经被淘汰了

public class SafeServlet extends HttpServlet implements SingleThreadModel {
    private String message = "";

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        message = "访问成功";
        PrintWriter writer = resp.getWriter();
        writer.println(message);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet( req,resp );
    }
}

尽可能使用局部变量:该方法任何一个客户进来都拿一个局部变量,所以此方式即可以就解决性能问题又能解决线程安全问题,推荐使用

public class SafeServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String message = "";
        message = "访问成功";
        PrintWriter writer = resp.getWriter();
        writer.println(message);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet( req,resp );
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来一沓Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值