Podríamos describir el ciclo de vida de un Servlet, someramente, de la siguiente forma
Si el Servlet sobre el que se ha realizado una petición no está cargado en el contenedor web, este crea una instancia de la clase Servlet, ejecuta su método init y posteriormente dará servicio con alguno de los métodos de servicio: doGet, doPost, doPut,…
En el caso que el Servlet esté cargado en el contenedor, cuando llega la petición, simplemente se encamina dicha petición a los métodos de servicio: doGet, doPost, doPut,…
Como podemos ver la diferencia es que en el segundo caso no se ejecuta el método de inicialización.
Los métodos de servicio de los Servlet se ejecutaran de forma concurrente por cada petición que llegue al contenedor web. Esto implica que, en el caso de existir recursos compartidos, como por ejemplo las variables de sesión, estos podrán ser accedidos al mismo instante.
Hasta el API Servlet 2.4 existía el interface SingleThreadModel. Dicho interface aseguraba que solo existiría una instancia en un momento concreto gestionando una petición. De tal manera que, si llegaba otra petición en ese momento, esta era encolada y procesada posteriormente.
public class ServletNoConcurrente extends HttpServlet implements SingleThreadModel{ ... }
Si bien, este interface ha sido declarado obsoleto debido a varios puntos:
- Producía degradamiento del sistema.
- No evitaba el tener que realizar controles de concurrencia sobre los recursos compartidos, ya que aunque en la petición se aseguraba un solo hilo, no implicaba que en otro punto se estuviese accediendo al mismo recurso.
Podéis leer más sobre el interface SingleThreadModel en el API de Java.