servlet生命周期和线程安全

  要想写一个servlet,可以继承GenericServlet或者可以继承HttpServlet,或者可以实现servlet接口,但是现在我们大多数网站都是http协议,而且httpservlet是继承自GenericServlet有很多重写的方法,所以现在我们只需要继承httpservlet就可以。

   servlet的生命周期分为三个阶段:

    1.初始化阶段,调用init()方法

    2.响应客户端请求,调用service()方法

    3.终止阶段,调用destroy()方法

  上面是一个servlet整个生命周期,整个的周期都不是我们程序员来调用或者说管理的,那么不是我们来调用的,是由谁来管理调用的?这里的是由web服务器来做的事情,当客户端请求一个servlet,这时服务器会为这个客户端初始化一个servlet,注意,这里是第一次访问,如果是第二次访问那么服务器会直接调用,不会在创建,那么服务器收到这个请求,根据资源地址对应到响应的servlet,这时服务器会调用当前servlet的service方法,来处理这个请求,处理完成后,响应给客户端。

  当一个servlet被创建,这个servlet会在服务器停止的时候被销毁。

  *************************************************

  servlet的线程安全:

  所谓的线程安全,就是多个线程同时或者共同访问同一个资源,这是会有线程安全的问题。

  代码实例:

 1 public class ServletDemo1 extends HttpServlet {
 2     int i = 0;
 3     @Override
 4     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
 5             throws ServletException, IOException {
 6         i++;
 7         try {
 8             Thread.sleep(1000*4);
 9         } catch (InterruptedException e) {
10             e.printStackTrace();
11         }
12         resp.getOutputStream().write((i+"").getBytes());
13     }
14     @Override
15     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
16             throws ServletException, IOException {
17         doGet(req, resp);
18     }
19 }

  上面这样写的话,给一个场景,有两个用户来访问,第一个用户开始访问,第二个紧接着访问,正常来说第一个用户应该得到的是1,但是这里却得到的是2,这里就是一个进程安全,那么这个怎么解决呢,有一个同步代码块,我们就把可能会出现线程安全的代码放在这个同步代码块里面,就可以避免这样的问题,

  

 1     int i = 0;
 2     @Override
 3     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
 4             throws ServletException, IOException {
 5         synchronized (this) {
 6             i++;
 7             try {
 8                 Thread.sleep(1000*4);
 9             } catch (InterruptedException e) {
10                 e.printStackTrace();
11             }
12             resp.getOutputStream().write((i+"").getBytes());
13         }
14         
15     }

  这样就能解决线程安全问题,但是这个synchronized同步代码块执行的原理是,第一个用户请求完成了,我才去解决第二个请求,这个能把人逼疯啊,

  还有一个方法能决绝但是,这个过时了,不提倡试用,就是你这个servlet实现标记接口SingleThreadModel类,这个类里面什么都没有,空接口,这样的接口我们称之为标记接口。

 1 public class ServletDemo1 extends HttpServlet implements SingleThreadModel{
 2     int i = 0;
 3     @Override
 4     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
 5             throws ServletException, IOException {
 6         i++;
 7         try {
 8             Thread.sleep(1000*4);
 9         } catch (InterruptedException e) {
10             e.printStackTrace();
11         }
12         resp.getOutputStream().write((i+"").getBytes());
13     }
14     @Override
15     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
16             throws ServletException, IOException {
17         doGet(req, resp);
18     }
19 }
如果有使用请标明来源:http://www.cnblogs.com/duwenlei/
原文地址:https://www.cnblogs.com/duwenlei/p/3487582.html