Before
discussing about Asynchronous processing, lets observe the below
Servlet Application.
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(urlPatterns = {"/ProcessRequest"}) public class ProcessRequest extends HttpServlet { @Override public void doGet(HttpServletRequest req, HttpServletResponse res)throws IOException, ServletException{ try(PrintWriter out = res.getWriter()){ String time = req.getParameter("time"); int wait = Integer.parseInt(time); String threadName = Thread.currentThread().getName(); long startTime = System.currentTimeMillis(); out.println("Thread " + threadName + " started at " + startTime); Thread.sleep(wait); long endTime = System.currentTimeMillis(); out.println("Thread " + threadName + " finished at " + endTime); out.println("Total time taken is " +(endTime-startTime) + " Milli Seconds"); } catch(InterruptedException e){ } } }
Output
Run
the above servlet like below.
time
is passed as query string. Servlet simply reads the time parameter in
query string and waits for that much time, and sends the response to
the client.
In
the above servlet are we really doing anything with request and
response objects ?
No,
But the thread associated with this request can't do anything until
the sleep finishes. These kind of long running tasks leads to thread
starvation. Since our servlet thread is blocked until all the
processing is done, if server gets a lot of requests to process, it
will hit the maximum servlet thread limit and further requests will
get Connection Refused errors.
As
an Application developer, you must ensure that no threads associated
with a request are sitting idle, so the container can use them to
process new requests. Asynchronous processing provides a facility to
assign these blocking operations to a new thread and retuning the
thread associated with the request immediately to the container.
If
a servlet or a filter reaches a potentially blocking operation when
processing a request, it can assign the operation to an asynchronous
execution context and return the thread associated with the request
immediately to the container without generating a response. The
blocking operation completes in the asynchronous execution context in
a different thread, which can generate a response or dispatch the
request to another servlet.
Example
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.AsyncContext; @WebServlet(urlPatterns = {"/ProcessRequest"}, asyncSupported=true) public class ProcessRequest extends HttpServlet { @Override public void doGet(HttpServletRequest req, HttpServletResponse res)throws IOException, ServletException{ final AsyncContext acontext = req.startAsync(); String threadName = Thread.currentThread().getName(); long startTime = System.currentTimeMillis(); System.out.println("Thread " + threadName + " started at " + startTime); acontext.start(new Runnable() { public void run() { String time = req.getParameter("time"); int wait = Integer.parseInt(time); try{ Thread.sleep(wait); } catch(InterruptedException e){ } HttpServletResponse response = (HttpServletResponse)acontext.getResponse(); try(PrintWriter out = response.getWriter()) { out.println("I am done"); } catch(Exception e){ } acontext.complete(); } }); long endTime = System.currentTimeMillis(); System.out.println("Thread " + threadName + " finished at " + endTime); System.out.println("Total time taken is " +(endTime-startTime) + " Milli Seconds"); } }
Run
the above servlet like below.
As
you see the console logs, you can observe the below information
messages immediately.
Info:
Thread http-listener-1(5) started at 1405140693455
Info:
Thread http-listener-1(5) finished at 1405140693456
Info:
Total time taken is 1 Milli Seconds
After
10 seconds you can see the response in your browser.
WebServlet(urlPatterns
= {"/ProcessRequest"}, asyncSupported=true)
public
class ProcessRequest extends HttpServlet {…}
To
enable asynchronous processing on a servlet, set the parameter
asyncSupported to true on the @WebServlet annotation as follows:
final
AsyncContext acontext = req.startAsync();
above
statement is used to get Asynchronous context. The
javax.servlet.AsyncContext class provides the functionality that you
need to perform asynchronous processing inside service methods. This
call puts the request into asynchronous mode and ensures that the
response is not committed after exiting the service method.
acontext.start(new
Runnable(){..});
The
container provides a different thread in which the blocking operation
can be processed.
Servlet
API provides below methods to support Asynchronous processing.
AsyncContext
getAsyncContext()
boolean
isAsyncStarted()
boolean
isAsyncSupported()
AsyncContext
startAsync()
AsyncContext
startAsync(ServletRequest servletRequest, ServletResponse
servletResponse)
No comments:
Post a Comment