Servlet singleton multithreading

How does a servlet handle multiple request access?
By default, the servlet container processes multiple requests in a single-instance multi-threaded manner:
1. When the web server starts (or when the client sends a request to the server), the servlet is loaded and instantiated (only one servlet instance exists);
 2. The container initializes the servlet mainly by reading configuration files (such as tomcat, You can set the number of threads in the thread pool through the <Connector> of servlet.xml , initialize the thread pool through web.xml, initialize each parameter value, etc.
 3. When the request arrives, the servlet container schedules it through the Dispatchaer Thread Manage the threads waiting to be executed in the thread pool (Worker Thread) to the requester;
 4. The thread executes the service method of the servlet;
 5. When the request ends, put it back into the thread pool and wait to be called;
(Note: Avoid using instance variables (member variables), because if there are member variables, it may happen that when multiple threads access the resource at the same time, they will all operate it, resulting in inconsistent data, thus causing thread safety issues)

From the above it can be seen that:
First: Servlet single instance, reducing the overhead of generating servlets;
Second: Responding to multiple requests through the thread pool improves the response time of requests;
Third: The servlet container does not care whether the arriving servlet request accesses the same servlet or another servlet, and directly assigns it a new thread; if it is multiple requests from the same servlet, the service method of the servlet will be in the Concurrent execution in multiple threads;
Fourth: Each request is accepted by the ServletRequest object, and the request is responded to by the ServletResponse object;

Compared with ASP and PHP, Servlet /JSP technology has high execution efficiency due to its multi-threaded operation. Since Servlet/ JSP is executed in multi-threaded mode by default, the security of multi-threading needs to be carefully considered when writing code.

Multithreading problems in JSP:
When the client requests a JSP file for the first time, the server compiles the JSP into a CLASS file, creates an instance of this class, and then creates a thread to process the client's request. If multiple clients request the JSP file at the same time, the server will create multiple threads. Each client request corresponds to a thread. Executing in multi-threaded mode can greatly reduce the resource requirements of the system and improve the concurrency and response time of the system.

The variables that may be used in JSP are described as follows:
Instance variables: Instance variables are allocated on the heap and shared by all threads belonging to the instance, so they are not thread-safe.
8 class variables provided by the JSP system
OUT, REQUEST, RESPONSE, SESSION, CONFIG, PAGE, PAGECONXT used in JSP are thread-safe (because the request and response objects corresponding to each thread are different, there is no sharing problem), APPLICATION is in the whole system is used, so it is not thread safe.

Local variables: Local variables are allocated on the stack and are thread-safe because each thread has its own stack space.
Static classes: Static classes can be used directly without being instantiated and are not thread-safe.

External resources: There may be multiple threads or processes operating on the same resource at the same time in the program (for example, multiple threads or processes write to a file at the same time). At this time, attention should also be paid to synchronization issues.

Make it execute in a single-threaded manner, at this time, there is still only one instance, and all client requests are executed in a serial manner. This will reduce the performance of the system

question
Question 1. Explain how the servlet container uses a single-instance multi-threading method to process requests
Question 2. How to ensure that the servlet works in a single-instance multi-threaded manner during development (that is, how to develop a thread-safe servlet).

1. How does the servlet container handle multiple requests at the same time

Java Memory Model JMM (Java Memory Model)
JMM is mainly to specify some relationships between threads and memory. According to the design of JMM, there is a main memory (Main Memory) in the system. All instance variables in Java are stored in the main memory and are shared for all threads. Each thread has its own working memory (Working Memory). The working memory consists of two parts: the cache and the stack. The cache stores a copy of the variables in the main memory. The cache may not always be synchronized with the main memory, that is, the variables in the cache The modification of the thread may not be written to the main memory immediately; the thread's local variables are saved in the stack, and the threads cannot directly access the variables in the stack with each other. According to JMM, we can abstract the memory model of the servlet instance discussed in the paper into the model shown in the figure.

 

Worker thread Work Thread: A set of threads that execute code.
Dispatcher Thread: Each thread has a thread priority assigned to it, and the thread is scheduled to execute according to the priority.

Servlet uses multi-threading to process multiple requests at the same time. servlets rely on a thread pool to serve requests. A thread pool is actually a collection of worker threads. Servlets use a dispatch thread to manage worker threads.

When the container receives a servlet request, the scheduling thread selects a worker thread from the thread pool, passes the request to the worker thread, and then executes the service method of the servlet by the thread. When this thread is executing, the container receives another request, and the scheduling thread also selects another worker thread from the thread pool to serve the new request. The container does not care whether the request accesses the same servlet. When When the container receives multiple requests to the same servlet at the same time, the service() method of the servlet will be executed concurrently in multiple threads.
By default, the servlet container uses a single-instance multi-threading method to process requests, which reduces the overhead of generating servlet instances and improves the response time to requests. For Tomcat, the number of threads in the thread pool can be set through the <Connector> element in server.xml. .

As far as implementation goes:
The responsibility of the scheduler thread class is just like its name. The responsibility of this class is to schedule threads, and it only needs to use its own properties to complete its responsibility. So the class is responsible, and the responsibility of the class is concentrated in a single single object. And other objects depend on the responsibility of the specific object, we need to get the specific object. That class is an implementation of the singleton pattern.


Note: The server can use multiple instances to handle requests, instead of the benefit of queuing requests for a single instance. The server creates an instance pool composed of multiple servlet instances of the servlet class, allocates a servlet instance to each request for response processing, and then puts it back into the instance pool to wait for the request. This creates the problem of concurrent access.
At this time, local variables (fields) are also safe, but they are not safe for global variables and shared data, and need to be synchronized. For such multiple instances, the SingleThreadModel interface cannot solve the problem of concurrent access. The SingleThreadModel interface has been deprecated in the servlet specification.

How to develop thread-safe servlets
  1. Implement the SingleThreadModel interface

  This interface specifies how the system handles calls to the same servlet. If a servlet is specified by this interface, then the service method in this servlet will not have two threads executed at the same time, and of course there is no thread safety problem. This method only needs to change the class header definition of the previous Concurrent Test class to:

Public class Concurrent Test extends HttpServlet implements SingleThreadModel { 
…………
}

  2. Synchronize operations on shared data

  Using the synchronized keyword can ensure that only one thread can access the protected section at a time. The servlet in this paper can ensure thread safety through synchronized block operations. The code after synchronization is as follows:

…………
Public class Concurrent Test extends HttpServlet { ………… 
Username = request.getParameter ("username"); 
Synchronized (this){ 
Output = response.getWriter (); 
Try {
Thread. Sleep (5000); 
} Catch (Interrupted Exception e){}
output.println("用户名:"+Username+"<BR>"); 
}
}
}

  3. Avoid using instance variables

  The thread safety problem in this example is caused by the instance variable. As long as the instance variable is not used in any method in the servlet, the servlet is thread safe.

  Modify the above Servlet code and change the instance variable to a local variable to achieve the same function. The code is as follows:

……
Public class Concurrent Test extends HttpServlet {public void service (HttpServletRequest request, HttpServletResponse 
Response) throws ServletException, IOException { 
Print Writer output;
String username;
Response.setContentType ("text/html; charset=gb2312"); 
……
}
}


 **  Test the above three methods, it can be shown that thread-safe Servlet programs can be designed with them. However, if a servlet implements the SingleThreadModel interface, the servlet engine will create a separate servlet instance for each new request, which will cause a lot of overhead. SingleThreadModel is no longer advocated in Servlet2.4; also, if synchronization is used in the program to protect the shared data to be used, the performance of the system will be greatly reduced. This is because the synchronized code block can only have one thread executing it at a time, which reduces the throughput of processing client requests at the same time, and many clients are blocked. In addition, in order to ensure the consistency of the main memory content and the data in the working memory of the thread, the cache should be refreshed frequently, which will also greatly affect the performance of the system. Therefore, the synchronization code in Servlet should also be avoided or minimized in actual development; avoiding the use of instance variables in Serlet is the best choice to ensure Servlet thread safety. It can also be known from the Java memory model that the temporary variables in the method are allocated space on the stack, and each thread has its own private stack space, so they will not affect thread safety.
More detailed instructions:

1. Thread safety of variables: variables here refer to fields and shared data (such as form parameter values).
a, Localize parameter variables. Multithreading does not share local variables. So we want to use local variables in servlet as much as possible.
For example: String user = "" ;
user = request.getParameter("user"); 

b. Use synchronized blocks Synchronized to prevent code blocks that may be called asynchronously. This means that threads need to be queued for processing. When using the same section, you should reduce the scope of synchronization code as much as possible, and do not use synchronization directly on the sevice method and the response method, which will seriously affect the performance.

2. Thread safety of attributes: attributes in ServletContext, HttpSession, and ServletRequest objects.
ServletContext: (thread is unsafe)
ServletContext can read / write attributes at the same time by multiple threads, and the threads are not safe. To synchronize the reading and writing of properties or perform deep Clone(). Therefore, the data that will be modified (written) is saved as little as possible in the servlet context, and can be shared among multiple servlets in other ways. For example, we can use the singleton pattern to process shared data.
HttpSession: (thread is unsafe)
The HttpSession object exists during the user session and can only be accessed in the thread processing the request belonging to the same Session, so the attribute access of the Session object is theoretically thread-safe.
When the user opens multiple browser windows that belong to the same process, and the access to these windows belongs to the same session, there will be multiple requests, and multiple worker threads are required to process the requests, which may result in simultaneous multi-threaded read and write attributes. At this time, we need to synchronize the reading and writing of properties: use the synchronized block Synchronized and use the reader / writer to solve it.
ServletRequest: (thread safe)
For each request executed by a worker thread, a new ServletRequest object is created, so the ServletRequest object can only be accessed in one thread. ServletRequest is thread safe. Note: The ServletRequest object is valid within the scope of the service method, do not try to keep a reference to the request object after the service method ends.

3. Use a synchronized collection class:
Use Vector instead of ArrayList and Hashtable instead of HashMap.

4. Don't create your own thread in Servlet to complete a function.
Servlet itself is multi-threaded. Creating threads in servlets will complicate the execution and cause multi-thread security issues.

5. The modification operation of external objects (such as files) in multiple servlets must be locked to achieve mutually exclusive access.

6. The javax.servlet.SingleThreadModel interface is an identification interface. If a servlet implements this interface, the servlet container will ensure that only one thread can be executed in the service method of a given servlet instance at a time. Queue all other requests.


PS:
Servlet is not just a singleton. When the container starts to start, or when the client sends a request for service, the Container will be responsible for loading and instantiating a servlet according to the configuration of the container (it can also be configured as multiple, but generally it is not done). However, Generally a servlet has only one instance.
1 ) The Action of Struts2 is a prototype, not a single instance; for each request, an Action instance is generated to process. 
2 ) Action of Struts1, beans managed by Spring's Ioc container are single instance by default.

Struts1 Action is a single instance, so is the controller of spring mvc. Therefore, it is required to be thread-safe during development, because only one instance of Action handles all requests. The singleton strategy limits what Struts1 Actions can do and requires special care during development. Action resources must be thread-safe or synchronized.
Spring's Ioc container-managed beans are single-instance by default.
Struts2 Action objects generate an instance for each request, so there is no thread safety issue. (Actually, the servlet container produces many discardable objects per request and doesn't cause performance and garbage collection issues).
When Spring manages the Action of Struts2, the bean is a single instance by default, which can be set as a prototype through configuration parameters. (scope ="prototype")




Servlet life cycle:

1. Servlet is loaded and instantiated when the web server starts, the container runs its init method to initialize, and runs its service method when the request arrives;

2. The doXXX(doGet, doPost) method corresponding to the service running request;

3. The server destroys the instance and runs its destroy method;

The life cycle of servlets is managed by the servlet container;

(Understanding of three concepts:

Servlet container < web container < application server?

The main task of the servlet container is to manage the life cycle of the servlet;

A web container is also called a web server, and its main task is to manage and deploy web applications;

The function of the application server is very powerful. It can not only manage and deploy web applications, but also deploy EJB applications, implement container-managed transactions, and so on. . .


The Web server deals with HTTP-based requests, while the EJB container interacts with the database, transaction management and other service interfaces, so the application server has many functions.

A common web server is Tomcat, but Tomcat is also a Servlet server;

Common application servers include WebLogic and WebSphere, but they are all charged;

Without a servlet container, you can use a web container to directly access static Html pages, such as apache installed; if you need to display Jsp / Servlet, you need to install a servlet container; but a servlet container is not enough, it needs to be parsed into html display , so a web container is still needed; therefore, we often regard the web container and the servlet container as one, because the two containers have implemented the functions of each other, and there is no independent existence, such as tomcat!



How does a servlet handle multiple requests being accessed at the same time?

By default, the servlet container processes multiple requests in a single-instance multi-threaded manner:

1. When the web server starts (or when the client sends a request to the server), the servlet is loaded and instantiated (only one servlet instance exists);

2. The container initializes the servlet. The main thing is to read the configuration file (such as tomcat, you can set the number of threads in the thread pool through <Connector> of servlet.xml, and initialize the thread pool; through web.xml, initialize each parameter value, etc.);

3. When the request arrives, the servlet container dispatches the waiting thread (Worker Thread) in the thread pool under its management to the requester through the dispatching thread (Dispatchaer Thread);

4. The thread executes the service method of the Servlet;

5. When the request ends, put it back into the thread pool and wait until it is called;

From the above it can be seen that:

First: Servlet single instance, reducing the overhead of generating servlets;

Second: Responding to multiple requests through the thread pool improves the response time of requests;

Third: The servlet container does not care whether the arriving servlet request accesses the same servlet or another servlet, and directly assigns it a new thread; if it is multiple requests from the same servlet, the service method of the servlet will be in the Concurrent execution in multiple threads;

Fourth: Each request is accepted by the ServletRequest object, and the request is responded to by the ServletResponse object;


Problem occurred:

When multiple requests from the same servlet arrive, if there is a member variable in the servlet, it may happen that when multiple threads access the resource at the same time, they all operate it, resulting in inconsistent data and thread safety issues.

solve:

1. Implement the SingleThreadModel interface

If a servlet is specified by this interface, then the service method in this servlet will not be executed by two threads at the same time, and of course there is no thread safety problem;

2. Synchronize operations on shared data

Using the synchronized keyword ensures that only one thread can access the protected section at a time. Servlets can ensure thread safety by synchronizing block operations.

ServletRequest objects are thread-safe, but ServletContext and HttpSession are not thread-safe;

To use a synchronized collection class: Vector instead of ArrayList, HsahTable instead of HashMap;

3. Avoid instance variables (member variables)

Thread safety is caused by instance variables. As long as instance variables are not used in any method in a servlet, the servlet is thread safe. (It is recommended not to define member variables in servlet, try to use local variables instead)


Testing the above three methods shows that thread-safe servlet programs can be designed using them. However, if a servlet implements the SingleThreadModel interface, the servlet engine will create a separate servlet instance for each new request, which will cause a lot of overhead. SingleThreadModel is no longer advocated in Servlet2.4; also, if synchronization is used in the program to protect the shared data to be used, the performance of the system will be greatly reduced. This is because the synchronized code block can only have one thread executing it at a time, which reduces the throughput of processing client requests at the same time, and many clients are blocked. In addition, in order to ensure the consistency of the main memory content and the data in the working memory of the thread, the cache should be refreshed frequently, which will also greatly affect the performance of the system. Therefore, the synchronization code in Servlet should be avoided or minimized in actual development; avoiding the use of instance variables in Serlet is the best choice to ensure Servlet thread safety. It can also be known from the Java memory model that the temporary variables in the method are allocated space on the stack, and each thread has its own private stack space, so they will not affect thread safety.

 The thread safety problem of Servlet will only appear when there is a large number of concurrent accesses, and it is difficult to find, so special attention should be paid when writing Servlet programs. Thread safety problems are mainly caused by instance variables, so instance variables should be avoided in servlets. If the application design cannot avoid the use of instance variables, then use synchronization to protect the instance variables that will be used, but to ensure the best performance of the system, the code paths with the least availability should be synchronized.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324916559&siteId=291194637