1. ホーム
  2. multithreading

[解決済み] サーブレットベースのWebアプリケーションでバックグラウンドタスクを実行するには?

2022-12-23 03:21:05

質問

Javaを使用していて、アプリケーション内でサーブレットを継続的に実行させたいのですが、その方法がわかりません。私のサーブレットは、データベースからのユーザーのカウントを毎日提供し、データベース全体からのユーザーの総カウントを提供するメソッドを持っています。だから私はそのためにサーブレットを継続的に実行したいのです。

どのように解決するのですか?

あなたの問題は、あなたが サーブレット . これは HTTP リクエストを処理するためのものであり、それ以上のものではありません。毎日一度だけ実行されるバックグラウンドタスクが必要なのです。

EJBが使える?利用する @Schedule

EJBをサポートしている環境(WildFly, JBoss, TomEE, Payara, GlassFishなどの本物のJava EEサーバ)の場合は @Schedule を代わりに使ってください。以下はその例です。

@Singleton
public class BackgroundJobManager {

    @Schedule(hour="0", minute="0", second="0", persistent=false)
    public void someDailyJob() {
        // Do your job here which should run every start of day.
    }

    @Schedule(hour="*/1", minute="0", second="0", persistent=false)
    public void someHourlyJob() {
        // Do your job here which should run every hour of day.
    }

    @Schedule(hour="*", minute="*/15", second="0", persistent=false)
    public void someQuarterlyJob() {
        // Do your job here which should run every 15 minute of hour.
    }

    @Schedule(hour="*", minute="*", second="*/5", persistent=false)
    public void someFiveSecondelyJob() {
        // Do your job here which should run every 5 seconds.
    }

} 

はい、本当にこれだけです。コンテナが自動的にピックアップして管理してくれます。

EJBが使えない?使用する ScheduledExecutorService

もしあなたの環境がEJBをサポートしていない場合(つまり、本物のJava EEサーバーではなく、TomcatやJettyなどの基本的なサーブレットコンテナーを使用している場合)、次のように使用します。 ScheduledExecutorService . これは ServletContextListener . 以下はキックオフの例です。

@WebListener
public class BackgroundJobManager implements ServletContextListener {

    private ScheduledExecutorService scheduler;

    @Override
    public void contextInitialized(ServletContextEvent event) {
        scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate(new SomeDailyJob(), 0, 1, TimeUnit.DAYS);
        scheduler.scheduleAtFixedRate(new SomeHourlyJob(), 0, 1, TimeUnit.HOURS);
        scheduler.scheduleAtFixedRate(new SomeQuarterlyJob(), 0, 15, TimeUnit.MINUTES);
        scheduler.scheduleAtFixedRate(new SomeFiveSecondelyJob(), 0, 5, TimeUnit.SECONDS);
    }

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

}

ジョブクラスがこうなっているところ。

public class SomeDailyJob implements Runnable {

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

}

public class SomeHourlyJob implements Runnable {

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

}

public class SomeQuarterlyJob implements Runnable {

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

}

public class SomeFiveSecondelyJob implements Runnable {

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

}

を使おうとは決して思わないでください。 java.util.Timer / java.lang.Thread Java EE / サーブレットベースの環境において

最後になりますが は決して を直接使用しないでください。 java.util.Timer とか java.lang.Thread を使用することができます。これはトラブルの元です。同じ質問に対するこのJSF関連の回答で、詳しい説明があります。 タイマーを使用してスケジュールされたタスクのためにJSFマネージドBeanでスレッドを生成する .