2013-02-20 79 views
1

我想在運行在Tomcat上的servlet上每22分鐘運行一次方法。所以我用這個代碼:定時器在Tomcat服務器上導致問題

Timer timer = new Timer(); 

timer.schedule(new TimerTask() { 
    @Override 
    public void run() { 

     try { 
      update(); 
     } catch (SQLException | NamingException | InterruptedException e1) { 
      e1.printStackTrace(); 
     } 
    } 
}, 22 * 60 * 1000, 22 * 60 * 1000); 

我有一種感覺,這是做它作爲我收到錯誤的所有關於定時器的時間的可怕的方式,每當我上傳的新版本servlet我認爲它不會停止前一個計時器。然後我得到數據庫連接警告。如果我重置一切,並開始新鮮的罰款。

javax.naming.NameNotFoundException: Name comp is not bound in this Context 
    at org.apache.naming.NamingContext.lookup(NamingContext.java:770) 
    at org.apache.naming.NamingContext.lookup(NamingContext.java:153) 
    at org.apache.naming.SelectorContext.lookup(SelectorContext.java:152) 
    at javax.naming.InitialContext.lookup(InitialContext.java:411) 
    at my.app.database.DatabaseManager.connect(DatabaseManager.java:44) 
    at my.app.database.DatabaseManager.returnInfo(DatabaseManager.java:133) 
    at my.app.genParse.Generate.updateHistory(Generate.java:89) 
    at my.app.MyServer$1.run(MyServer.java:52) 
    at java.util.TimerThread.mainLoop(Timer.java:555) 
    at java.util.TimerThread.run(Timer.java:505) 

而且還重新推出新的版本:

SEVERE: The web application [/myApp] appears to have started a thread named [Timer-7] but has failed to stop it. This is very likely to create a memory leak. 

請告訴我一個更好的辦法來實現或避免這種情況?

回答

1

已經討論了使用計時器任務的替代方案here。使用ScheduledThreadpoolExecutorMAY有助於解決上載新版本時仍然運行多個線程的問題,但我無法確定它會這樣做。由於javadoc中討論的各種原因,該班級也優於Timer班。

+0

謝謝,我現在使用它,它似乎運行得更好。 – RegDHunter 2013-02-21 01:24:11

1

你真的不應該在容器中使用Timer - Timer產卵/重用在容器外管理的線程,這可能會導致問題。

還要注意,爲Timer使用單個線程,如果它的一個實例的時間太長了別人的精度會受到影響。

最後,如果Timer引發了未檢查的異常,則Timer線程將終止。

對於這些(及其他)原因已基本失寵的 - 的ScheduledThreadPoolExecutor是一個更好的選擇。

雖然如此,容器內用戶管理的線程可能會很棘手。 JSR-236(用於Java EE平臺的併發實用程序)將在未來提供一種機制,但現在最好避免這種做法。

您可以嘗試通過cron日程重複的任務或許可以依次調用專用的servlet(或類似)定期

0

使用的ServletContextListener來啓動和停止計時器Web應用程序啓動和停止時。