Servlets are really parts of an application and require a servlet container to run. This servlet container is responsible for instantiating your servlet and calling the appropriate methods in the servlet at the appropriate times.
When you type the name of a servlet, you are really making a call to a program that is located on a server and not on your machine. At first, this process seems like magic, but after a little study you will see that this process only requires that each piece of software in the process perform a fairly simple set of tasks. Figure 21.1 shows this process graphically.
Figure 21.1. . The servlet container is responsible for instantiating your servlets.
You type in the URL of a servlet that you want to call.
The browser creates a request that contains the servlet and the name of your machine so that the server will know who to send feedback to.
The server receives the request and hands it to the servlet container. The servlet container is a program that knows how to run servlets.
The servlet container checks to see if any instances of this servlet are already in memory. If not, it loads an instance and runs the servlet's init() method.
The servlet container waits for the init() method to finish. It then calls the service() method in your servlet from a new thread.
The service() method calls the doGet() or doPost() method depending on what the request type is.
A second user's browser requests that the same servlet be run on its behalf.
The servlet container notices that an instance of the servlet is already in memory. So, it creates a new thread and starts running the same servlet that you are running.
This new thread calls the service() method.
If this is an HTTP servlet, the service() method calls the doGet() or doPost() methods.
The first thread finishes and a response is sent to the Web server, which forwards it to your browser.
The second thread finishes and a response is sent to the Web server, which forwards it to the second user's browser.
At a certain point in the future, the servlet container decides to deinstantiate the servlet. At that point it calls the destroy() method once for each instance in memory.
Whether more than one instance of a single servlet is in memory depends on whether it is declared to be thread-safe. A servlet is assumed to be thread-safe unless it implements the SingleThreadModel interface. If it implements this interface, a new instance will be created for each simultaneous access. This has serious performance penalties associated with it, so it should only be done if absolutely necessary.