1. はじめに
タイマー (Timer) は、指定された時間の後に実行されるか、指定された間隔で繰り返されるタスク (java.util.TimerTask) をスケジュールするためのユーティリティ クラスです。これを使用して、タイミング タスク、タイミング スケジューリング、時間遅延などの操作を実行できます。
タイマー (タイマー) は、次のような多くのシナリオに適用できます。
タスクのスケジュール設定 (固定レート) : スケジュールされた時間に従ってタスクを実行する必要がある場合は、タイマーを使用できます。たとえば、データのバックアップが毎朝実行され、レポートが定期的に生成され、通知が定期的に送信されます。つまり、scheduleAtFixedRate の 2 つのオーバーロードされたメソッドです。
タイムアウト処理 (固定遅延) : 操作のタイムアウトを処理する必要がある場合は、タイマーを使用できます。たとえば、操作のタイムアウト時間を設定し、指定された時間内に操作が完了しない場合は、対応するタイムアウト処理ロジックを実行します。つまり、スケジュールの 4 つの多重定義メソッドです。
Java のタイマー: java.util.Timer、その一般的なメソッド:
Java 8 中国語版 - オンライン API マニュアル - コーディングツール
修飾子とタイプ |
方法と説明 |
パラメータの説明 |
空所 |
キャンセル() このタイマーを終了し、現在スケジュールされているタスクをすべて破棄します。 |
/ |
整数 |
パージ() キャンセルされたすべてのタスクをこのタイマーのタスク キューから削除します。 |
/ |
空所 |
指定したタスクを指定した時刻に実行するようにスケジュールします。この時間が経過した場合は、タスクをすぐに実行するようにスケジュールします。 |
タスク: スケジュールされるタスク time : タスクの実行時間 |
空所 |
スケジュール( TimerTask タスク、 日付 firstTime、長期) 指定された 時間に開始して、指定されたタスクの固定遅延実行を 繰り返し 実行します 。 |
タスク: スケジュールされるタスク firstTime: タスクが初めて実行された時刻 period: 連続タスクの時間間隔 (ミリ秒単位) |
空所 |
指定された遅延の後に指定されたタスクが実行されるようにスケジュールします。 |
タスク: スケジュールされるタスク 遅延: タスクを実行するまでの遅延時間 (ミリ秒) |
空所 |
スケジュール( TimerTask タスク、長い遅延、長期間) 指定された 遅延の後に開始し 、 固定遅延で実行された指定されたタスクを再実行します。 |
タスク: スケジュールされるタスク 遅延: タスクを実行するまでの遅延時間 (ミリ秒) period: 連続タスクの時間間隔 (ミリ秒単位) |
空所 |
scheduleAtFixedRate ( TimerTask タスク、 日付 firstTime、長期) 指定された時間に 開始して 、指定されたタスクを 固定レートで繰り返し実行します 。 |
タスク: スケジュールされるタスク firstTime: タスクが初めて実行された時刻 period: 連続タスクの時間間隔 (ミリ秒単位) |
空所 |
scheduleAtFixedRate ( TimerTask タスク、長い遅延、長い期間) 指定された遅延の後に 開始され、指定されたタスクが固定レートで 再実行されます 。 |
タスク: スケジュールされるタスク 遅延: タスクを実行するまでの遅延時間 (ミリ秒) period: 連続タスクの時間間隔 (ミリ秒単位) |
2.scheduleとscheduleAtFixedRateメソッドの違い
これら 2 つの方法はタスク スケジューリング方法です。これらの違いは、スケジュールでは、定義された期間パラメーターに従ってタスク間の間隔が厳密に実行されることを保証することです。特定のスケジュール時間が比較的長い場合、次の時間は延期されます。スケジュール間隔を確保する これらはすべて期間であり、scheduleAtFixedRate はスケジュール時間に厳密に従っています。特定のスケジュール時間が長すぎる場合は、次のスケジュールがスケジュールされた時間に実行されるように、間隔が短くなります。栗を例に挙げます。3 秒ごとに 1 回スケジュールすると、通常の時間は 0、3、6、9 秒になります。2 番目のスケジュールに 2 秒かかる場合、スケジュールの場合、0、3 + 2 になります。8 のような時間の場合は、 ,11、間隔が保証され、scheduleAtFixedRate は 0,3+2,6,9 になり、間隔が圧縮され、スケジュール時間が保証されます。
3. ステップを使ったタイマー(Timer)
時間指定タスクを実装するには、TimerTask の run メソッドを実装するだけです。各タスクには次回実行時刻 nextExecutionTime (ミリ秒) が設定されています。定期タスクの場合、各実行は今回の時刻を次回実行時刻として更新します。nextExecutionTime が現在時刻より小さい場合、実行されます。
(1) 最初のステップ: タイマーを作成します。
(2) 2 番目のステップ: TimerTask を作成します。
(3) 3 番目のステップ: Timer を使用して TimerTask を実行します。
3 番目のステップは、間違いなく現時点で最も懸念していること、つまり timer.schedule(myTask, 2000L, 1000L) です。つまり、myTask は 2 秒後に初めて実行を開始し、その後は 1 秒ごとに実行が開始されるということです。これは最も基本的な使い方です。タイマーのタイミング実行のプロセスを反映します。
例1 : タイムアウト処理 (固定遅延)
2 秒後に 1 回のみ実行を開始します
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimeTest {
public static void main(String[] args) {
System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
Timer timer = new Timer(); // (1)第一步:创建一个Timer。
timer.schedule(new TimerTask() { // (2)第二步:创建一个TimerTask。(3)第三步:使用Timer执行TimerTask。
@Override
public void run() {
System.out.println("Timer is running");
System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
}
}, 2000);
}
}
操作結果:
現在の時刻: 2023-08-19 22-45-46:161
タイマーが作動中です
現在の時刻: 2023-08-19 22-45-48:169
例2 : タスクのスケジュール設定 (固定レート)
定期的なタスクを実行するには、スケジュールの 3 番目のパラメーター period を追加するだけです。
2秒後に実行を開始し、1秒ごとに実行
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimeTest {
public static void main(String[] args) {
System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
Timer timer = new Timer(); // (1)第一步:创建一个Timer。
timer.schedule(new TimerTask() { // (2)第二步:创建一个TimerTask。(3)第三步:使用Timer执行TimerTask。
@Override
public void run() {
System.out.println("Timer is running");
System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
}
}, 2000, 1000);
}
}
操作結果:
現在の時刻: 2023-08-19 22-48-10:190
タイマーが作動中です
現在の時刻: 2023-08-19 22-48-12:200
タイマーが作動中です
現在の時刻: 2023-08-19 22-48-13:203
タイマーが作動中です
現在の時刻: 2023-08-19 22-48-14:216
例3 : 2 つのタイマー インスタンスがタスクをスケジュールします (固定レート)
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimeTest {
public static void main(String[] args) {
System.out.println("timer当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
Timer timer = new Timer(); // (1)第一步:创建一个Timer。
timer.schedule(new TimerTask() { // (2)第二步:创建一个TimerTask。(3)第三步:使用Timer执行TimerTask。
@Override
public void run() {
System.out.println("Timer is running");
System.out.println("timer当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
}
}, 2000, 1000);
System.out.println("timer2当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
Timer timer2 = new Timer(); // (1)第一步:创建一个Timer。
timer2.schedule(new TimerTask() { // (2)第二步:创建一个TimerTask。(3)第三步:使用Timer执行TimerTask。
@Override
public void run() {
System.out.println("Timer2 is running");
System.out.println("timer2当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
}
}, 3000, 2000);
}
}
操作結果:
タイマー現在時刻: 2023-08-20 00-08-06:746
Timer2 現在時刻: 2023-08-20 00-08-06:748
タイマーが作動中です
タイマー現在時刻: 2023-08-20 00-08-08:750
タイマーが作動中です
タイマー2が実行中です
Timer2 現在時刻: 2023-08-20 00-08-09:755
タイマー現在時刻: 2023-08-20 00-08-09:755
タイマーが作動中です
タイマー現在時刻: 2023-08-20 00-08-10:769
タイマー2が実行中です
Timer2 現在時刻: 2023-08-20 00-08-11:768
タイマーが作動中です
タイマー現在時刻: 2023-08-20 00-08-11:784
タイマーが作動中です
タイマー現在時刻: 2023-08-20 00-08-12:787
タイマー2が実行中です
Timer2 現在時刻: 2023-08-20 00-08-13:770
4. タイマーの不具合
1. タスクを実行するスレッドが 1 つしかないため、あるタスクの実行時間が長すぎると、他のタスクのタイミング精度が崩れてしまいます。たとえば、1 つのタスクが 1 秒ごとに実行され、別のタスクの実行に 5 秒かかる場合、それが固定レートのタスクであれば、タスクが 5 秒で完了した後、そのタスクは 5 回実行されます。遅延タスクは 4 回の実行を失います。
2. 特定のタスクの実行中に例外がスローされると、実行スレッドが終了し、タイマー内の他のタスクが実行されなくなります。
3. タイマーは絶対時間、つまり特定の時点を使用するため、その実行はシステム時刻に依存し、システム時刻が変更されるとタスクが実行されなくなる可能性があります。
5. より良い代替案
Timer の上記の欠陥のため、JDK1.5 では、ScheduledThreadPoolExecutor を使用して置き換えるか、Executors.newScheduledThreadPool ファクトリ メソッドを使用するか、ScheduledThreadPoolExecutor のコンストラクタを使用して、スレッド プールの実装に基づいた時限タスクを作成できます。タイマには上記の問題があり、スレッド数が 1 の場合、タイマと同等になります。