web-dev-qa-db-ja.com

定期的な間隔で実行するタスクをスケジュールするにはどうすればよいですか?

私はスケジュールされたタスクを実装するためにいくつかのコードを試していて、これらのコードを思いつきました。

import Java.util.*;

class Task extends TimerTask {


    int count = 1;

    // run is a abstract method that defines task performed at scheduled time.
    public void run() {
        System.out.println(count+" : Mahendra Singh");
        count++;
    }
}

class TaskScheduling {

   public static void main(String[] args) {
       Timer timer = new Timer();


       // Schedule to run after every 3 second(3000 millisecond)
       timer.schedule( new Task(), 3000);   
   }
}

私の出力:

1  :  Mahendra Singh

コンパイラーは3秒の定期的な間隔で一連のMahendra Singhを印刷することを期待していましたが、約15分間待機しているにもかかわらず、1つの出力しか得られません...これを解決するにはどうすればよいですか?

73
Vimal Basdeo

timer.scheduleAtFixedRate を使用します

public void scheduleAtFixedRate(TimerTask task,
                                long delay,
                                long period)

指定した遅延の後に開始して、固定レートの繰り返し実行のために指定したタスクをスケジュールします。後続の実行は、指定された期間で区切られたほぼ一定の間隔で行われます。
固定レートの実行では、各実行は、最初の実行のスケジュールされた実行時間に関連してスケジュールされます。何らかの理由(ガベージコレクションや他のバックグラウンドアクティビティなど)で実行が遅れると、2つ以上の実行が連続して発生し、「追いつき」ます。長期的には、実行の頻度は指定された期間の逆数になります(Object.wait(long)の基礎となるシステムクロックが正確であると仮定)。

固定レートの実行は、1時間ごとにチャイムを鳴らしたり、特定の時間に毎日定期メンテナンスを実行するなど、絶対時間に敏感な繰り返しアクティビティに適しています。また、一定の実行回数を実行する合計時間が重要である繰り返しのアクティビティにも適しています。たとえば、10秒間に1秒に1回カチカチと鳴るカウントダウンタイマーなどです。最後に、固定レートの実行は、相互に同期を維持する必要がある複数の繰り返しタイマータスクをスケジュールするのに適しています。

パラメーター:

  • task-スケジュールされるタスク。
  • delay-タスクが実行されるまでのミリ秒単位の遅延。
  • period-連続するタスク実行間のミリ秒単位の時間。

スロー:

  • IllegalArgumentException-遅延が負の場合、または遅延+ System.currentTimeMillis()が負の場合.
  • IllegalStateException-タスクがすでにスケジュールされているかキャンセルされているか、タイマーがキャンセルされているか、タイマースレッドが終了した場合。
69
st0le

ScheduledExecutorServiceに対するTimerの利点

ScheduledThreadPoolExecutorScheduledExecutorService インターフェースの実装を使用して、Timerの代替を提供したいと思います。 「Java in Concurrency」によると、Timerクラスに比べていくつかの利点があります。

Timerは、タイマータスクを実行するための単一のスレッドのみを作成します。タイマータスクの実行に時間がかかりすぎると、他のTimerTaskのタイミングの精度が低下する可能性があります。繰り返しのTimerTaskが10ミリ秒ごとに実行されるようにスケジュールされ、別のTimer-Taskの実行に40ミリ秒かかる場合、繰り返しタスク(固定レートまたは固定遅延でスケジュールされているかどうかによって異なります) -実行中のタスクが完了するか、4回の呼び出しが完全に「失敗」します。スケジュールされたスレッドプールは、遅延タスクおよび定期タスクを実行するための複数のスレッドを提供できるようにすることで、この制限に対処します。

Timerの別の問題は、TimerTaskが未チェックの例外をスローした場合の動作が悪いことです。また、「スレッド漏れ」と呼ばれる

タイマースレッドは例外をキャッチしないため、TimerTaskからスローされた未チェックの例外はタイマースレッドを終了します。この状況でも、タイマーはスレッドを復活させません。代わりに、タイマー全体がキャンセルされたと誤って想定しています。この場合、すでにスケジュールされているがまだ実行されていないTimerTasksは実行されず、新しいタスクをスケジュールすることはできません。

また、独自のスケジューリングサービスを構築する必要がある場合の別の推奨事項として、DelayQueueのスケジューリング機能を提供するBlockingQueue実装を使用して、ScheduledThreadPoolExecutorを使用することで、ライブラリを活用できる場合があります。 DelayQueueは、遅延オブジェクトのコレクションを管理します。 Delayedには遅延時間が関連付けられています。DelayQueueは、遅延が終了した場合にのみ要素を取得できます。オブジェクトは、DelayQueueから遅延に関連付けられた時間順に並べられて返されます。

74
Alexandr
public void schedule(TimerTask task,long delay)

指定された遅延の後、指定されたタスクの実行をスケジュールします。

あなたが欲しい:

public void schedule(TimerTask task, long delay, long period)

指定されたタスクを繰り返し固定遅延で実行するように、指定された遅延の後にスケジュールします。後続の実行は、指定された期間で区切られたほぼ定期的な間隔で行われます。

14
yurib

Quartzスケジューラーもソリューションであり、最初にQuartz Jobクラスを作成します。

クォーツジョブは実行したいものが定義されています

package com.blogspot.geekonjava.quartz;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
public class QuartzJob implements Job {
        public void execute(JobExecutionContext context)
                        throws JobExecutionException {
                JobKey jobKey = context.getJobDetail().getKey();
                System.out.println("Quartz" + "Job Key " + jobKey);
        }
}

ここで、クォーツトリガーを作成する必要があります

Quartzには2種類のトリガーがあります

SimpleTrigger–開始時間、終了時間、繰り返し間隔を設定できます。

Trigger trigger = newTrigger().withIdentity("TriggerName", "Group1")
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(10).repeatForever()).build();

CronTrigger– Unix cron式でジョブを実行する日時を指定できます。

Trigger trigger = newTrigger()
                .withIdentity("TriggerName", "Group2")
                .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")).build();

スケジューラクラスは、JobTriggerの両方をリンクして実行します。

Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
scheduler.scheduleJob(job, trigger);

ここに見ることができる完全な例

4
Tell Me How
timer.scheduleAtFixedRate( new Task(), 1000,3000); 
2
Brijesh

この目的のために、JavaにはTimerおよびTimerTaskクラスがありますが、それは何ですか?

  • Java.util.Timerは、将来の特定の時間に実行されるスレッドをスケジュールするために使用できるユーティリティクラスです。 Javaタイマークラスを使用して、タスクを1回実行するか、定期的に実行するようにスケジュールできます。
  • Java.util.TimerTaskはRunnableインターフェースを実装する抽象クラスです。このクラスを拡張して、Javaタイマークラス。

GeekonJavaから完全なチュートリアルを確認できます

TimerTask timerTask = new MyTimerTask();

//running timer task as daemon thread

Timer timer = new Timer(true);

timer.scheduleAtFixedRate(timerTask, 0, 10*1000);
1
Tell Me How