web容器可能決定一個Servlet是否從servic中移除(例如,當一個容器想要回收內存資源時或者被關閉時)。在上面的場景中,容器會調用Servlet接口的destroy方法。在方法中,能夠釋放servlet使用的任何資源,保存持久化狀態。destroy
方法關閉在init
方法中建立的數據庫對象。
當servlet被移除時,它的service方法必須所有執行完成。服務器在全部請求被響應或者在一個特定時間後,經過調用destroy
方法確保這一點的實現。當你的servlet正在執行超過服務器超時時間的長任務時,這些操做直到destroy
方法被調用前都在執行。你必須確保任何持有客戶端請求的線程完成。
本節的其他部分將介紹如何執行如下操做:java
要跟蹤服務請求,須要在servlet類中包含一個變量,這個變量用來統計運行的service方法數量。這個變量須要使用同步方法增量、減量和返回變量值。web
public class ShutdownExample extends HttpServlet { private int serviceCounter = 0; ... // Access methods for serviceCounter protected synchronized void enteringServiceMethod() { serviceCounter++; } protected synchronized void leavingServiceMethod() { serviceCounter--; } protected synchronized int numServices() { return serviceCounter; } }
當每次進入service方法時都須要增加變量值,每次離開service方法時都須要減少變量值。這是你要在HttpServlet子類覆寫父類service方法的緣由之一。新方法須要調用super.service()保留原始的service方法的內容。數據庫
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException { enteringServiceMethod(); try { super.service(req, resp); } finally { leavingServiceMethod(); } }
爲了確保一個乾淨的關閉,在全部請求完成前你的service方法不能釋聽任何共享資源。作到這一點的一部分是檢查service的數量。另一部分是通知長時間運行的任務是時候關閉了。爲了能通知到位,須要另外一個變量。這個變量須要有一般的訪問方法。服務器
public class ShutdownExample extends HttpServlet { private boolean shuttingDown; ... //Access methods for shuttingDown protected synchronized void setShuttingDown(boolean flag) { shuttingDown = flag; } protected synchronized boolean isShuttingDown() { return shuttingDown; } }
下面是一個使用這些變量提供乾淨的關閉方法的示例:線程
public void destroy() { /* Check to see whether there are still service methods /* /* running, and if there are, tell them to stop. */ if (numServices()> 0) { setShuttingDown(true); } /* Wait for the service methods to stop. */ while (numServices()> 0) { try { Thread.sleep(interval); } catch (InterruptedException e) { } } }
提供乾淨關閉的最後一步是使任何長時間運行的方法都比較規範。可能須要長期運行的方法須要檢查通知他們關閉的變量並在須要時強制打斷正在執行的工做。code
public void doPost(...) { ... for(i = 0; ((i < lotsOfStuffToDo) && !isShuttingDown()); i++) { try { partOfLongRunningOperation(i); } catch (InterruptedException e) { ... } } }