In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces "the method of using Servlet asynchronous mode under tomcat". In the daily operation, I believe that many people have doubts about the method of using Servlet asynchronous mode under tomcat. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts about "the method of using Servlet asynchronous mode under tomcat". Next, please follow the editor to study!
After the servlet3.0 version, support for asynchronous mode has been added.
In the past, in servlet, each new request was received and processed by a thread. If you need to wait for the results of other operations, the thread will be blocked and unable to perform other tasks. After the task ends, the thread will output the results to the client, then the thread can continue to process other requests. In order to improve the efficiency of thread utilization, the servlet3.0 version has added an asynchronous request processing mode, which allows the current thread to submit tasks to other background threads for processing (usually a background thread pool, so that fewer threads are needed to handle a large number of tasks) and receive new requests instead.
Protected void service (final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {response.getWriter () .println ("hello");}
To use asynchronous mode, simply call the startAsync method of the request object, which returns an AsyncContext object for subsequent use, through which you can set the timeout for asynchronous processing, add listeners for asynchronous processing, and so on. The task to be processed is then submitted to a thread pool, and the current thread can process other new requests after executing subsequent code, without waiting for the current task to finish. After the current task is executed by the background thread pool, you can call the asyncContext.complete method to indicate that the task processing is complete, and trigger the previously added listener to respond to the event.
Protected void service (final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {/ / enable asynchronous mode final AsyncContext ac = request.startAsync (); / / timeout set ac.setTimeout (1000L) / / adding listeners makes it easier to observe events that occur ac.addListener (new AsyncListener () {@ Override public void onComplete (AsyncEvent asyncEvent) throws IOException {System.out.println ("onComplete");} @ Override public void onTimeout (AsyncEvent asyncEvent) throws IOException {System.out.println ("onTimeout")) } @ Override public void onError (AsyncEvent asyncEvent) throws IOException {System.out.println ("onError");} @ Override public void onStartAsync (AsyncEvent asyncEvent) throws IOException {System.out.println ("onStartAsync");}}) Executor.submit (new Runnable () {@ Override public void run () {/ / you can use request, response,ac and other objects try {String user = request.getParameter ("user"); response.getWriter () .println ("hello from async" + user) Ac.complete ();} catch (IOException e) {e.printStackTrace ();}); / / method ends the current thread is ready to process other requests}
Because the asyncContext object holds the request and response objects in the request, you can still output the results to the client through response after the task is executed asynchronously. However, tomcat does not receive the complete message after the timeout, so it thinks that the asynchronous task has timed out and needs to end the current request, thus putting the response object back into the object pool for other requests to continue to use. At this point, the response object is assigned to the new request and should no longer be shared by previous asynchronous tasks! But the asynchronous task itself does not know that the task has timed out and continues to run, so it also uses the response object for output, which leads to the phenomenon that the new request and the background asynchronous task share a resonse object! This causes multiple threads to output the results to the same client, which is not what the client needs. Just imagine: the original request was to inquire about my order list, but as a result, I received a list of other people's orders. is this consequence very serious?
To verify this problem, you can test it with the following code:
Package async;import javax.servlet.AsyncContext;import javax.servlet.AsyncEvent;import javax.servlet.AsyncListener;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class AsyncTimeoutServlet extends HttpServlet {boolean running = false; boolean stop = false ThreadPoolExecutor executor = new ThreadPoolExecutor (1,1500L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue); @ Override public void init () throws ServletException {System.out.println ("init AsyncTimeoutServlet");} @ Override public void destroy () {executor.shutdownNow ();} protected void service (final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {stop = "true" .equals (request.getParameter ("stop")) / / Asynchronous mode is used only for the first request, and subsequent requests use the synchronous mode if (running) {System.out.println ("running"); try {/ / outputs the hashcode response.getWriter () .println ("this response belong's to you:" + response.toString ()) of the response object in synchronous mode. } catch (IOException e) {System.out.println ("response error");} return;} running = true; / / enable asynchronous mode final AsyncContext ac = request.startAsync (); System.out.println ("startAsync"); / / timeout is set to 1s to facilitate fast timeout ac.setTimeout (1000L) / / adding listeners makes it easier to observe events that occur ac.addListener (new AsyncListener () {@ Override public void onComplete (AsyncEvent asyncEvent) throws IOException {System.out.println ("onComplete");} @ Override public void onTimeout (AsyncEvent asyncEvent) throws IOException {System.out.println ("onTimeout")) } @ Override public void onError (AsyncEvent asyncEvent) throws IOException {System.out.println ("onError");} @ Override public void onStartAsync (AsyncEvent asyncEvent) throws IOException {System.out.println ("onStartAsync");}}) Executor.submit (new Runnable () {@ Override public void run () {while (! stop) {try {/ / output the result to the original response object every 3s, so that the client can observe whether it has received the result Thread.sleep (3000L). System.out.println ("async run"); try {response.getWriter (). Println ("if you see this message, something must be wrong. Isimm "+ response.toString ();} catch (IOException e) {System.out.println (" async response error ");}} catch (InterruptedException e) {e.printStackTrace (); return } System.out.println ("stop");}}); System.out.println ("ok, async mode started.");}}
In the above test example, we turned on asynchronous mode for the first request, and the subsequent requests were still in synchronous mode, and simply output the hashcode of the response object, committing a task to the thread pool to run. In an asynchronous task, the hashcode of the response object is output to the client every 3 seconds, and this response object is the first requested response object, that is, it should use a different response object than subsequent requests. However, after calling the servlet many times, the results of some requests contain the output from the asynchronous task generated by the first request, that is, some subsequent requests share the same response object as the first request, and tomcat reuses the response object!
The test results are as follows:
Curl-I "http://127.0.0.1:8080/servlet_async/async"HTTP/1.1 200 OKServer: Apache-Coyote/1.1Content-Length: 192Date: Wed, 21 Aug 2019 07:55:26 GMTif you see this message, something must be wrong. Isimm org.apache.catalina.connector.ResponseFacade@51582d92this response belong's to you:org.apache.catalina.connector.ResponseFacade@51582d92
Not every request can be successfully reused to the same response, so the above request may need to be run multiple times to produce the desired results.
Methods of avoiding pits:
If an asynchronous task needs to use a response object, it first determines whether the current asynchronous mode has timed out and ended, and if it is finished, do not use the object again, and it is the same with the request object. However, sometimes we pass the request object to the asynchronous task and take some data from it when the task is executed, such as getting parameters from getParameter. In this case, we can get all the data needed by the asynchronous task in advance from the request object and encapsulate it into a new object for use by the asynchronous task to avoid using the request object provided by tomcat.
At this point, the study on "the method of using Servlet asynchronous mode under tomcat" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.