Difference between the servlet single threaded model and multi threaded model

Typically, a servlet class is instantiated the first time it is invoked. The same instance will be used over several client requests, so all members that are declared in that servlet are shared accross clients. That is what is meant by multi threaded model, multiple clients that access the same instance.

There are situations where you want to protect your servlet member variables from being modified by different clients. In this case, you can have your servlet implement the marker interface SingleThreadModel. Every time a client makes a request to a servlet that implements this interface, the engine will create a new instance of the servlet. For performance reasons, the engine can also maintain a instance pool, handing out instances as they are needed. Or it could also serialize client requests, executing one after another.

To see the differences in action, check out the following servlets.

MultiThread Servlet

Open up two browser instances, have both of them point to http://www.esus.com/servlets/MultiThread . The servlet code is simple. It saves some state in a variable, sleeps for 10 seconds and finally checks if that state has been changed during its nap. Since this is a multi threaded model servlet, the second client will change the internal state of the servlet. The first servlet is confused after its snooze.

The code for this servlet can be found below.

SingleThread Servlet

Again, open up two browser instances, have both of them point to http://www.esus.com/servlets/SingleThread. The code is the same as in MultiThread, except that it implements the marker interface SingleThreadServlet. Now notice that the state of the first client is not affected by the second client.

MultiThread.java:

import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;
 
public class MultiThread extends HttpServlet
{ 
   int hashCode;
 
   public void doGet (HttpServletRequest request,
                      HttpServletResponse response) 
                  throws ServletException, IOException
   {
      PrintWriter out;
      hashCode = request.hashCode();
 
      response.setContentType("text/html");
 
      out = response.getWriter();
           
      out.println("<HTML><HEAD><TITLE>");
      out.println("MultiThread Servlet");
      out.println("</TITLE></HEAD><BODY bgcolor="#FFFFFF">");
 
      // sleep for 10 seconds
      try {
         Thread.sleep(10000);
      }
      catch(InterruptedException e) { }
 
      // check if state has changed
      if (hashCode == request.hashCode()) {
         out.println("<H1> I am me! </H1> " + "[" + hashCode + "]");
      }
      else {
         out.println("<H1> I am someone else! </H1>" + "[" + hashCode + "]");
      }
  
      out.println("</BODY></HTML>");
      out.close();
   }
}

SingleThread.java:

import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;
 
public class SingleThread extends HttpServlet implements SingleThreadModel
{ 
   int hashCode;
 
   public void doGet (HttpServletRequest request,
                      HttpServletResponse response) 
                  throws ServletException, IOException
   {
      PrintWriter out;
      hashCode = request.hashCode();
 
      response.setContentType("text/html");
 
      out = response.getWriter();
           
      out.println("<HTML><HEAD><TITLE>");
      out.println("MultiThread Servlet");
      out.println("</TITLE></HEAD><BODY bgcolor="#FFFFFF">");
 
      // sleep for 10 seconds
      try {
         Thread.sleep(10000);
      }
      catch(InterruptedException e) { }
 
      // check if state has changed
      if (hashCode == request.hashCode()) {
         out.println("<H1> I am me! </H1> " + "[" + hashCode + "]");
      }
      else {
         out.println("<H1> I am someone else! </H1>" + "[" + hashCode + "]");
      }
  
      out.println("</BODY></HTML>");
      out.close();
   }
}