2013-03-27 71 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