6

Apache Tomcat で JSP/Servlet を使用しています。10 分ごとにメソッドを実行する必要があります。どうすればこれを達成できますか?

4

2 に答える 2

10

必要最小限のサーブレット コンテナである Tomcat を使用@Scheduleしているため、Java EE 仕様で推奨されている EJB を使用することはできません。あなたの最善の策は、ScheduledExecutorServiceJava 1.5のjava.util.concurrentパッケージからです。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 をサポートし、すべて em (Glassfish、JBoss AS、TomEE など) を備えた実際の Java EE コンテナを使用している場合は@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のようなベアボーンサー​​ブレットコンテナには別のオプションがありません。

Timer「ライフタイム ロング」実行中の Java EE Web アプリケーションでは、を決して使用しないでください。Java EE での使用に適さない次の主要な問題があります ( Java Concurrency in Practiceから引用)。

  • Timerシステムクロックの変更に敏感です。そうでScheduledExecutorServiceはありません。
  • Timerには実行スレッドが 1 つしかないため、実行時間の長いタスクが他のタスクを遅らせる可能性があります。ScheduledExecutorService任意の数のスレッドで構成できます。
  • TimerTaskその 1 つのスレッドを強制終了して実行時例外がスローされると、Timerデッドになります。つまり、スケジュールされたタスクは (サーバーを再起動するまで) 実行されなくなります。ScheduledThreadExecutor実行時例外をキャッチするだけでなく、必要に応じてそれらを処理できます。例外をスローしたタスクはキャンセルされますが、他のタスクは引き続き実行されます。
于 2013-04-03T14:03:26.663 に答える
3

ScheduledExecutorServiceを読み取り、 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();
    }
}

また、ServletContextListenerからJavaタイマーを使用することもできますが、コンテナーからスレッド リソースの制御が奪われるため、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、その implementsTimerTaskRunnableインターフェイスを実装するクラスであるため、run メソッドをコードでオーバーライドする必要があります。

class MyTask extends TimerTask 
{
  public void run() 
  { 
    // your code here
  }
}
于 2013-04-03T12:44:17.157 に答える