重要声明:本文章仅仅代表了作者个人对此观点的理解和表述。读者请查阅时持自己的意见进行讨论。
一、需求
在业务开发中常常出现将结果回调给对接渠道的需求,而回调为了保证成功,通常都会有一个失败重试的功能,这样就需要有一个重试规则,并有一个比较好的机制来处理,而又不关心任务是否可控。
二、实现
根据这样一个需求,可以使用Java提供的Timer来实现,下面是代码。
/**
* 按rule指定的规则执行 fun 方法<br>
* 规则的指定: "0 60 120 200"<br>
* 含义:立刻执行一次方法,待60秒执行一次,再待120秒执行,依次推类,单位始终为秒。<br>
* 若某一次执行后,后续不希望再执行,d0 方法请返回 true;<br>
* @param fun 要执行的方法。
* @param rule 规则。
*/
public static void runWithRule(final Fun fun, String rule) {
final String[] times = rule.split(" ");
final Timer timer = new Timer();
final int[] timeIndex = {0};
timer.schedule(
newTimerTask(fun, timeIndex, times, timer),
Integer.parseInt(times[timeIndex[0]]) * 1000
);
}
private static TimerTask newTimerTask(
final Fun fun,
final int []timeIndex,
final String[] times,final Timer timer
) {
return new TimerTask() {
@Override
public void run() {
boolean success = fun.d0();
// 返回值是 false, 表示后续要继续执行。
if (!success) {
// 已经执行完了所有规则。
if (timeIndex[0] >= (times.length - 1)) {
timer.cancel();
return;
}
timeIndex[0]++;
timer.schedule(
newTimerTask(fun, timeIndex, times, timer),
Integer.parseInt(times[timeIndex[0]]) * 1000
);
} else {
// 返回值是true, 不用再执行了。
}
}
};
}
public interface Fun{
boolean d0();
}
其中分出了一个私有方法,每次timer进行任务注入是,都是使用new的新的TimerTask,TimerTask不能重用,因此提取一个方法出来作为创建TimerTask的私有方法。
三、使用
现在,只需要使用暴露的 runWithRule
即可完成对应功能:
public static void main(String[] args) {
// 打印程序开始时间,方便对比
System.out.println(new Date());
// 调用工具方法
runWithRule(new Fun() {
@Override
public boolean d0() {
System.out.println(new Date());
return false;
}
}, "1 5 5 10");
}
输出结果:
Tue Sep 03 10:32:03 CST 2019 // 这是第一行打印的程序开始时间。
Tue Sep 03 10:32:04 CST 2019 // 过1秒,执行任务了,与规则符合。
Tue Sep 03 10:32:09 CST 2019 // 过5秒执行,与规则符合。
Tue Sep 03 10:32:14 CST 2019 // 过5秒执行,符合。
Tue Sep 03 10:32:24 CST 2019 // 过10秒执行,符合。
yeah!
Full text complete, Reproduction please indicate the source. Help you? Not as good as one:
Comment(Comments need to be logged in. You are not logged in.)
You need to log in before you can comment.