0
点赞
收藏
分享

微信扫一扫

JavaWeb学习指南 - 初窥Servlet线程安全问题

一脸伟人痣 2022-01-09 阅读 22

文章目录

1. 线程安全的概念

  • 服务器在收到请求之后,会启动一个线程来进行相应的请求处理。

  • 默认情况下,服务器为每个Servlet只创建一个对象实例。当多个请求访问同一个Servlet时,会有

    多个线程访问同一个Servlet对象,此时就可能发生线程安全问题。

  • 多线程并发逻辑,需要使用synchronized对代码加锁处理,但尽量避免使用。

2. 线程安全的案例

  • ThreadServlet

    package cn.knightzz.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    /**
     * @author 王天赐
     * @title: ThreadServlet
     * @projectName spring-aop-01
     * @description:
     * @website http://knightzz.cn/
     * @github https://github.com/knightzz1998
     * @date 2022/1/9 9:56
     */
    @WebServlet(name="ThreadServlet", urlPatterns = "/thread-servlet")
    public class ThreadServlet extends HttpServlet {
    
        /**
         * 共享变量
         */
        private String name;
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doPost(req, resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 获取参数
            name = req.getParameter("name");
    
            // 睡眠5s, 模拟并发
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            // 获取输出流
            PrintWriter writer = resp.getWriter();
            writer.println("<h2>" + name + "</h2>");
            writer.close();
        }
    }
    
    
  • thread.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Servlet线程安全测试</title>
    </head>
    <body>
    
    <iframe width="400px" height="100px" src="thread-servlet?name=zhang"></iframe>
        <br/>
    <iframe width="400px" height="100px" src="thread-servlet?name=wang"></iframe>
        <br/>
    <iframe width="400px" height="100px" src="thread-servlet?name=li"></iframe>
    
    </body>
    </html>
    
  • 下图为执行结果, 如下图所示 , 正常情况下, 每个iframe 的值是不同的, 但是由于并发访问, 此时显示都是 <h2>li</h2>

image-20220109102640748

3. 线程安全的解决方案

  • 在共享变量上面加锁

     @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            synchronized (this) {
                // 获取参数
                name = req.getParameter("name");
    
                // 睡眠5s, 模拟并发
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                // 获取输出流
                PrintWriter writer = resp.getWriter();
                writer.write("<h2>" + name + "</h2>");
                writer.close();
            }
        }
    
  • 执行结果如下

    image-20220109103554340

举报

相关推荐

0 条评论