Although it is standard to have one servlet instance per registered servlet name, it is possible for a servlet to elect instead to have a pool of instances created for each of its names, all sharing the duty of handling requests. Such servlets indicate this desire by implementing the javax.servlet.SingleThreadModel interface. This is an empty, tag interface that defines no methods or variables and serves only to flag the servlet as wanting the alternate life cycle.
A server that loads a SingleThreadModel servlet must guarantee, according to the Servlet API documentation, "that no two threads will execute concurrently the service method of that servlet." To accomplish this, each thread uses a free servlet instance from the pool, as shown in Figure 3-4. Thus, any servlet implementing SingleThreadModel can be considered thread safe and isn't required to synchronize access to its instance variables.
Such a life cycle is pointless for a counter or other servlet application that requires central state maintenance. The life cycle can be useful, however, in avoiding synchronization while still performing efficient request handling.
For example, a servlet that connects to a database sometimes needs to perform several database commands atomically as part of a single transaction. Normally, this would require the servlet to synchronize around the database commands (letting it manage just one request at a time) or to manage a pool of database connections where it can "check out" and "check in" connections (letting it support multiple concurrent requests). By instead implementing SingleThreadModel and having one "connection" instance variable per servlet, a servlet can easily handle concurrent requests by letting its server manage the servlet instance pool (which doubles as a connection pool). The skeleton code is shown in Example 3-5.
import java.io.*; import java.sql.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class SingleThreadConnection extends HttpServlet implements SingleThreadModel { Connection con = null; // database connection, one per pooled servlet instance public void init(ServletConfig config) throws ServletException { super.init(config); // Establish the connection for this instance con = establishConnection(); con.setAutoCommit(false); } public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/plain"); PrintWriter out = res.getWriter(); // Use the connection uniquely assigned to this instance Statement stmt = con.createStatement(); // Update the database any number of ways // Commit the transaction con.commit(); } public void destroy() { if (con != null) con.close(); } private Connection establishConnection() { // Not implemented. See Chapter 9, "Database Connectivity". } }
Copyright © 2001 O'Reilly & Associates. All rights reserved.
This HTML Help has been published using the chm2web software. |