概要:
Timer是一种定时器工具,用来在一个后台线程计划执行指定任务。它可以安排任务“执行一次”或者定期“执行多次”。
然而在实际的开发过程当中,经常需要一些周期性的操作,比如每5分钟执行某一操作等。
对于这样的操作最方便、高效的实现方式就是使用java.util.Timer工具类。
メソッドの概要:
schedule(TimerTask task, Date time) // 安排在 "指定的时间" 执行 指定的任务。(只执行一次)
schedule(TimerTask task,long delay) // 安排在指定延迟后执行指定的任务
schedule(TimerTask task, Date firstTime , long period) // 安排指定的任务在 "指定的时间 " 开始进行 "重复" 的固定延迟执行
schedule(TimerTask task,long delay,long period)// 安排指定的任务指定的延迟后开始进行重复的固定延迟执行.
scheduleAtFixedRate(TimerTask task,Date firstTime,long period)// 安排指定的任务在指定的时间开始进行重复的固定速率执行.
scheduleAtFixedRate(TimerTask task,long delay,long period)//安排指定的任务在指定的延迟后开始进行重复的固定速率执行.
Timer.cancal()// 终止此计时器,丢弃所有当前已安排的任务。
Timer.purge()// 从此计时器的任务队列中移除所有已取消的任务。
TimerTask.cancal()// 把当前任务取消
Fixed Delay: 最後の実行が開始されてからしばらくしてから実行が開始されることを意味します。つまり、タスクの次の実行時間は、最後の実際の実行が完了した時点に相対的であるため、実行時間は引き続き遅延します。
固定頻度: 前回の実行が遅れたかどうかに関係なく、各実行が最初のスケジュールに準拠することを意味します。つまり、タスクの次の実行時間は最後の実行時点に関連しているため、実行時間が遅れることはありません
これら 2 つのスケジューリング方法について、それらの使用方法を見てみましょう。
固定遅延スケジューリングを使用するために、schedule() メソッドには 2 つのオーバーロードもあり、それぞれがミリ秒単位で周期性を示す追加パラメーターを取ります。なぜ 2 回オーバーロードするのですか? ある時点で、または少し遅れてタスクを開始する可能性があるためです。
固定レートのスケジューリングに関しては、周期もミリ秒単位の 2 つの scheduleAtFixedRate() メソッドがあります。同様に、特定の日時にタスクを開始するメソッドと、特定の遅延後にタスクを開始するメソッドがあります。
1 つの注意: タスクが実行期間より長くかかる場合、固定遅延または固定レートのどちらを使用しても、実行チェーン全体が遅延します。(固定レートは継続的に実行され、固定遅延は遅延を待ってから実行されます)
特定のコード
schedule(TimerTask タスク, 日時)
/**
* @PROJECT_NAME: demo
* @DESCRIPTION: 指定时间执行
*/
public class TimerDemo {
public static void main(String[] args) {
Calendar ca = Calendar.getInstance();
System.out.println(ca.getTime());
ca.set(Calendar.SECOND, ca.get(Calendar.SECOND) + 5);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
System.out.println(new Date(scheduledExecutionTime());
}
}, ca.getTime());
}
}
スケジュール (TimerTask タスク、長い遅延)
/**
* @PROJECT_NAME: demo
* @DESCRIPTION: 延迟指定时间后执行
*/
public class DelayDemo {
public static void main(String[] args) {
System.out.println(new Date());
new Timer().schedule(new TimerTask() {
@Override
public void run() {
System.out.println(new Date(scheduledExecutionTime());
}
}, 2000);
}
}
schedule(TimerTask タスク, Date firstTime, 長期)
/**
* @PROJECT_NAME: demo
* @DESCRIPTION: 安排指定的任务在 "指定的时间 " 开始进行 "重复" 的固定延迟执行
*/
public class FirstAndPeriodDemo {
public static void main(String[] args) {
Calendar ca = Calendar.getInstance();
System.out.println(ca.getTime());
ca.set(Calendar.SECOND, ca.get(Calendar.SECOND) + 2);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(new Date(scheduledExecutionTime()));
}
}, ca.getTime(),2000);
}
}
最初のタスクが 2 秒遅れ、スレッドの実行時間が 3 秒であるため、タスクの最後に次のタスクが開始されます。
スケジュール (TimerTask タスク、長い遅延、長い期間)
/**
* @PROJECT_NAME: demo
* @DESCRIPTION: 安排指定的任务在“指定的延迟”后开始进行“重复”的固定延迟执行
*/
public class DelayAndPeriodDemo {
public static void main(String[] args) {
System.out.println(new Date());
new Timer().schedule(new TimerTask() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(new Date(scheduledExecutionTime()));
}
}, 1000,2000);
}
}
scheduleAtFixedRate(TimerTask タスク,Date firstTime,長期)
/**
* @PROJECT_NAME: demo
* @DESCRIPTION:
*/
public class FixAndFirstDemo {
public static void main(String[] args) {
System.out.println(new Date());
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(new Date(scheduledExecutionTime()));
}
}, 1000, 2000);
}
}
固定レートで実行されます。
ただし、ここで別の問題が発生します。Timer はシングルスレッドで内部的に実装されているため、実行間隔が 2 秒でタスクの実際の実行時間が 3 秒の場合、scheduleAtFixedRate はどのように 2 秒に 1 回出力されるのでしょうか?
【注意を払う】
これは実際には目隠しです。print メソッドによって出力される値は、scheduledExecutionTime() を呼び出すことによって生成されることに注意することが重要です。このメソッドは、必ずしもタスクの実際の実行時間ではなく、現在のタスクが実行されるべき時間です。
ソースコードの理解