Page 1 of 1
About Question enthuware.jwpv6.2.790 :
Posted: Mon May 09, 2016 9:27 pm
by himaiMinh
Code: Select all
@WebServlet(name = "MyAsyncServlet", urlPatterns = {"/MyAsyncServlet"} , asyncSupported=true)
public class MyAsyncServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
final AsyncContext ac = request.startAsync();
final HttpServletRequest localRequest = request;
//Attribute default_Age being set in the main thread of the servlet
localRequest.setAttribute("default_Age", "18");
System.out.println("Default age being set in the main thread: "+ (String)localRequest.getAttribute("default_Age"));
ac.start(new Runnable() {
public void run(){
//Attribute default_Age being set in another thread.
localRequest.setAttribute("default_Age","20");
System.out.println("Default age being set in the thread : "+(String)localRequest.getAttribute("default_Age"));
}
});
//This default age result is unexpected either 18 or 20.
//If the runnable thread runs after the main thread, it will be 20.
//If the main thread runs before the runnable thread , it will be 18.
System.out.println(" final default age : "+ (String)localRequest.getAttribute("default_Age"));
ac.complete();
}
}
Possible result:
Default age being set in the main thread: 18
final default age : 18
Default age being set in the thread : 20
Can this code example demonstrate the request object is not thread safe ?
Re: About Question enthuware.jwpv6.2.790 :
Posted: Mon May 09, 2016 9:46 pm
by admin
The code does show that request object is not thread safe. However, you are not allowed to create threads in a servlet. Servlet container cannot guarantee thread safely if you violate its conditions.
-Paul.
Re: About Question enthuware.jwpv6.2.790 :
Posted: Mon May 09, 2016 10:56 pm
by himaiMinh
Hi, Paul. Thanks for your reply.
So, I can first create a separate class which implements Runnable.
Then, I instantiate an instance of this class and pass it to AsyncContext.start() method as an argument?
Re: About Question enthuware.jwpv6.2.790 :
Posted: Tue May 10, 2016 4:29 pm
by himaiMinh
I refactored the code.
The servlet delegates the thread pool executor to execute the thread.
Code: Select all
package com.nullhaus;
....
@WebListener
public class MyContextListener implements ServletContextListener {
public void contextInitialized (ServletContextEvent servletContextEvent){
//create the thread pool
ThreadPoolExecutor executor = new ThreadPoolExecutor(100,200, 50000L,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(100));
servletContextEvent.getServletContext().setAttribute("executor", executor);
}
public void contextDestroyed (ServletContextEvent servletContextEvent){
ThreadPoolExecutor executor = (ThreadPoolExecutor)servletContextEvent.getServletContext().getAttribute("executor");
executor.shutdown();
}
}
Code: Select all
package com.nullhaus;
....
@WebServlet(name = "AsyncServlet1", urlPatterns = {"/AsyncServlet1"} , asyncSupported=true)
public class AsyncServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
final AsyncContext ac = request.startAsync();
final HttpServletRequest localRequest = request;
localRequest.setAttribute("default_Age", "18");
System.out.println("Default age being set in the main thread: "+ (String)localRequest.getAttribute("default_Age"));
ThreadPoolExecutor executor = (ThreadPoolExecutor)request.getServletContext().getAttribute("executor");
executor.execute( new MyRunnable(ac,localRequest));
System.out.println(" final default age : "+ (String)localRequest.getAttribute("default_Age"));
}
}
Code: Select all
package com.nullhaus;
...
public class MyRunnable implements Runnable{
private HttpServletRequest localRequest ;
private AsyncContext asyncCtx;
public MyRunnable(){}
public MyRunnable(AsyncContext asyncCtx, HttpServletRequest req){
this.asyncCtx = asyncCtx;
this.localRequest=req;
}
@Override
public void run() {
localRequest.setAttribute("default_Age","20");
System.out.println("Default age being set in MyRunnable thread : "+(String)localRequest.getAttribute("default_Age"));
asyncCtx.complete();
}
}
Reference:
https://www.javacodegeeks.com/2013/08/a ... let-3.html