2013-03-27 65 views
-1

我正在阅读关于“Servlet 3.0中的异步处理支持”(http://www.javaworld.com/javaworld/jw-02-2009/jw-02-servlet3.html?page=2)的专家(?)教程。在这里面有这个下面的代码片段:ServletContextListener:这不正确的用法吗?

@WebServlet(name="myServlet", urlPatterns={"/slowprocess"}, asyncSupported=true) 
public class MyServlet extends HttpServlet { 

    public void doGet(HttpServletRequest request, HttpServletResponse response) { 
     AsyncContext aCtx = request.startAsync(request, response); 
     ServletContext appScope = request.getServletContext(); 
     ((Queue<AsyncContext>)appScope.getAttribute("slowWebServiceJobQueue")).add(aCtx); 
    } 
} 

@WebServletContextListener 
public class SlowWebService implements ServletContextListener { 

    public void contextInitialized(ServletContextEvent sce) { 
     Queue<AsyncContext> jobQueue = new ConcurrentLinkedQueue<AsyncContext>(); 
     sce.getServletContext().setAttribute("slowWebServiceJobQueue", jobQueue); 
     // pool size matching Web services capacity 
     Executor executor = Executors.newFixedThreadPool(10); 
     while(true) 
     { 
      if(!jobQueue.isEmpty()) 
      { 
       final AsyncContext aCtx = jobQueue.poll(); 
       executor.execute(new Runnable(){ 
        public void run() { 
         ServletRequest request = aCtx.getRequest(); 
         // get parameteres 
         // invoke a Web service endpoint 
         // set results 
         aCtx.forward("/result.jsp"); 
        } 
       }); 
      } 
     } 
    } 

    public void contextDestroyed(ServletContextEvent sce) { 
    } 

}

因为,这是专家“这 - 是 - 如何-IT-IS-做”文章中,我假设他们不会是写一些愚蠢的代码。 但我无法接受'contextInitialized()'中有'while(true)'循环。

  1. 根据我的理解,此上下文侦听器线程永远不会退出'contextInitialized()'方法。对 ?
  2. 我的应用程序中有其他任何Servlet会发生什么?他们是否可以自由处理请求?或者这是否会导致整个servlet容器?
+0

此代码不会在contextDestroyed上清理,并且不会停止运行。 – 2013-03-27 19:18:44

回答

2

1)我会改变的代码如下:

@WebServletContextListener 
public class SlowWebService implements ServletContextListener, Runnable { 
    private volatile boolean running; 
    ExecutorService executor; 
    Thread runner; 
    Queue<AsyncContext> jobQueue; 

    public void contextInitialized(ServletContextEvent sce) { 
     jobQueue = new ConcurrentLinkedQueue<AsyncContext>(); 
     sce.getServletContext().setAttribute("slowWebServiceJobQueue", jobQueue); 
     // pool size matching Web services capacity 
     executor = Executors.newFixedThreadPool(10); 
     runner = new Thread(this); 
     runner.start(); 
    } 

    public void run() { 
     running = true; 
     while(running) 
     { 
      try { 
       if(!jobQueue.isEmpty()) 
       { 
        final AsyncContext aCtx = jobQueue.poll(); 
        executor.execute(new Runnable(){ 
         public void run() { 
          ServletRequest request = aCtx.getRequest(); 
          // get parameteres 
          // invoke a Web service endpoint 
          // set results 
          aCtx.forward("/result.jsp"); 
         } 
        }); 
       } 
      } 
      catch (InterruptException e) { 
      } 
     } 
    } 

    public void contextDestroyed(ServletContextEvent sce) { 
     running = false; 
     runner.interrupt(); 
     executor.shutdown(); 
    } 
} 

2)其他Servlet不应该,只要他们有不同的URL模式的影响。

+0

'executor'由'runner'线程和'context-listener-event-handling'线程访问。它是否应该以某种方式不稳定或同步? – brainOverflow 2013-03-27 19:55:50

+0

我假设将'running'设置为false并'中断'线程的原因是强制线程退出它的'poll'并让它看看它是否应该'运行'了。对 ? – brainOverflow 2013-03-27 20:12:35

+0

@vendhan是的,否则当上下文被破坏时线程不会停止。在这种情况下,您不需要同步执行程序。 – 2013-03-28 00:15:26