2013-04-03 43 views

回答

3

讀它必須由一個ServletContextListener

public class MyContext implements ServletContextListener 
{ 
    private ScheduledExecutorService sched; 

    @Override 
    public void contextInitialized(ServletContextEvent event) 
    { 
     sched = Executors.newSingleThreadScheduledExecutor(); 
     sched.scheduleAtFixedRate(new MyTask(), 0, 10, TimeUnit.MINUTES); 
    } 

    @Override 
    public void contextDestroyed(ServletContextEvent event) 
    { 
     sched.shutdownNow(); 
    } 
} 

也可啓動,您可以嘗試使用Java TimerServletContextListener,但它不是在一個Java EE容器推薦,因爲它帶走的控制線程資源從容器。 (ScheduledExecutorService的第一個選項是要走的路)。

Timer timer = new Timer("MyTimer"); 
MyTask t = new MyTask(); 

//Second Parameter is the specified the Starting Time for your timer in 
//MilliSeconds or Date 

//Third Parameter is the specified the Period between consecutive 
//calling for the method. 

timer.schedule(t, 0, 1000*60*10); 

而且MyTask實現TimerTask是一個類,所以你必須與你的代碼重寫run方法實現了Runnable接口:

class MyTask extends TimerTask 
{ 
    public void run() 
    { 
    // your code here 
    } 
} 
+0

好吧我得到了它,但從那裏我必須調用此方法。我必須在應用程序啓動後立即啓動 –

+2

[永遠不要在Java EE中使用Timer](http://stackoverflow.com/questions/9173132/stop-scheduled-timer-when-shutdown-tomcat/9186070#9186070 )。 – BalusC

+0

謝謝@BalusC我在我的回答中明確提到過。 – user1697575

10

當你在Tomcat中,這僅僅是一個準系統servlet容器,你不能使用EJB的@Schedule來達到Java EE規範推薦的目的。您最好的選擇是來自Java 1.5的java.util.concurrent包的ScheduledExecutorService。你可以用一個ServletContextListener喜歡幫助觸發此如下:

@WebListener 
public class BackgroundJobManager implements ServletContextListener { 

    private ScheduledExecutorService scheduler; 

    @Override 
    public void contextInitialized(ServletContextEvent event) { 
     scheduler = Executors.newSingleThreadScheduledExecutor(); 
     scheduler.scheduleAtFixedRate(new SomeTask(), 0, 10, TimeUnit.MINUTES); 
    } 

    @Override 
    public void contextDestroyed(ServletContextEvent event) { 
     scheduler.shutdownNow(); 
    } 

} 

其中SomeTask類是這樣的:

public class SomeTask implements Runnable { 

    @Override 
    public void run() { 
     // Do your job here. 
    } 

} 

如果你實際上使用與EJB支持和所有真正的Java EE容器em(像Glassfish,JBoss AS,TomEE等),那麼你可以使用@Singleton EJB和@Schedule方法。這樣容器就會擔心自己會集中並銷燬線程。所有你需要的是那麼下面的EJB:

@Singleton 
public class SomeTask { 

    @Schedule(hour="*", minute="*/10", second="0", persistent=false) 
    public void run() { 
     // Do your job here. 
    } 

} 

注意,這樣你就可以繼續使用透明容器管理事務的常用方式(@PersistenceContext等),這是不可能的ScheduledExecutorService —你必須手動獲取實體管理器並手動啓動/提交/結束事務,但是在默認情況下,您已經在像Tomcat這樣的準系統servlet容器上沒有其他選項。

請注意,您絕不應在運行Java EE Web應用程序的所謂「終生長」中使用Timer。它有這使得它不適合於Java EE中使用以下主要問題(從Java Concurrency in Practice引用):

  • Timer是系統時鐘的變化很敏感,ScheduledExecutorService不是。
  • Timer只有一個執行線程,所以長時間運行的任務可以延遲其他任務。 ScheduledExecutorService可以配置任意數量的線程。
  • TimerTask中拋出的任何運行時異常都會終止一個線程,從而導致Timer死機,即計劃任務將不再運行(直到您重新啓動服務器)。 ScheduledThreadExecutor不僅捕獲運行時異常,但它可以讓你處理它們,如果你想。拋出異常的任務將被取消,但其他任務將繼續運行。
+0

很好的答案,謝謝@BususC。有一個問題:如果我需要更改調用之間的間隔,我將如何修改調度程序? 例如我有一些'頻率',可以由用戶在webgui中設置,代表以秒爲單位的時間間隔。 – Gewure

相關問題