【Java】回调失败重试。使用Timer实现的定时任务,支持按规则执行。

一个支持按照指定时间执行方法的解决方案,可以以此实现类似对接渠道回调失败重试的功能。

【Java】回调失败重试。使用Timer实现的定时任务,支持按规则执行。

By img Microanswer Create at:Sep 3, 2019, 10:40:16 AM 

Tags: java timer 定时任务 失败重试

一个支持按照指定时间执行方法的解决方案,可以以此实现类似对接渠道回调失败重试的功能。


重要声明:本文章仅仅代表了作者个人对此观点的理解和表述。读者请查阅时持自己的意见进行讨论。

一、需求

在业务开发中常常出现将结果回调给对接渠道的需求,而回调为了保证成功,通常都会有一个失败重试的功能,这样就需要有一个重试规则,并有一个比较好的机制来处理,而又不关心任务是否可控。

二、实现

根据这样一个需求,可以使用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.

Comments (0 Comments)