一个轻量级重试工具类

代码较为简单,不做过多描述:

package util;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.LockSupport;

/**
 * <p>这是一套轻量级的重试框架</p>
 *
 * @date 2020年03月27日 10:07
 */
@Slf4j
public class RetryUtils {

    private static RetryEngine DEFAULT_ENGINE = new RetryEngine();

    /**
     * 默认的重试执行,3次,间隔1000ms
     * @param task  有返回值任务
     * @return 返回值
     */
    public static <T> T run(RetryTask<T> task) {
        return DEFAULT_ENGINE.run(task);
    }

    /**
     * 默认的重试执行,3次,间隔1000ms
     * @param task  无返回值任务
     */
    public static void run(VoidRetryTask task) {
        DEFAULT_ENGINE.run(task);
    }

    /**
     * 重试执行
     *
     * @param task          要重试的任务
     * @param maxAttempts   最大重试次数
     * @param period        每次重试间隔
     * @param <T>           返回值
     * @return              result
     */
    public static <T> T run(int maxAttempts, long period, RetryTask<T> task) {
        RetryEngine engine = generateRetryEngine(maxAttempts, period);
        return engine.run(task);
    }


    /**
     * 重试执行
     *
     * @param task          要重试的任务
     * @param maxAttempts   最大重试次数
     * @param period        每次重试间隔
     */
    public static void run(int maxAttempts, long period, VoidRetryTask task) {
        RetryEngine engine = generateRetryEngine(maxAttempts, period);
        engine.run(task);
    }


    /**
     * 构造一个重试器
     *
     * @param maxAttempts   最大重试次数
     * @param period        每次重试间隔
     * @return 重试器
     */
    public static RetryEngine generateRetryEngine(int maxAttempts, long period) {
        return new RetryEngine(maxAttempts, period);
    }

    @Data
    public static class RetryEngine {
        private int maxAttempts = 3;
        private long period = 1000L;
        private AfterThrowTask afterThrowTask;
        private FinalTask finalTask;

        public RetryEngine() {
        }

        public RetryEngine(int maxAttempts, long period) {
            this.maxAttempts = maxAttempts;
            this.period = period;
        }

        public <T> T run(RetryTask<T> task) {
            RetryContext context = new RetryContext(0, null, this);

            for (int i = 1; i <= maxAttempts; i++) {
                try {
                    return task.execute();
                } catch (Exception e) {
                    context.failCount = i;
                    context.exception = e;

                    log.info("- fail count = {}", context.failCount);
                    log.info("- error message:", context.exception);

                    if (afterThrowTask != null) {
                        afterThrowTask.execute(context);
                    }
                    if (i < maxAttempts) {
                        LockSupport.parkNanos(period * 1000000L);
                    }
                }
            }

            log.info("- retry failed after {} times!", maxAttempts);

            if (finalTask != null) {
                return finalTask.execute(context);
            }

            throw new RuntimeException(context.exception);
        }

        public void run(VoidRetryTask task) {
            RetryContext context = new RetryContext(0, null, this);

            for (int i = 1; i <= maxAttempts; i++) {
                try {
                    task.execute();
                    return;
                } catch (Exception e) {
                    context.failCount++;
                    context.exception = e;

                    log.info("- execute count = {}, fail count = {}", i, context.failCount);
                    log.info("- error message:", context.exception);

                    if (afterThrowTask != null) {
                        afterThrowTask.execute(context);
                    }
                    if (i < maxAttempts) {
                        LockSupport.parkNanos(period * 1000000L);
                    }
                }
            }

            log.info("- retry failed after {} times!", maxAttempts);

            if (finalTask != null) {
                finalTask.execute(context);
                return;
            }

            throw new RuntimeException(context.exception);
        }
    }



    public interface RetryTask<T> {
        T execute();
    }

    public interface VoidRetryTask {
        void execute();
    }

    public interface AfterThrowTask {
        void execute(RetryContext context);
    }

    public interface FinalTask {
        <T> T execute(RetryContext context);
    }

    public static class RetryContext {
        int failCount;
        Exception exception;
        RetryEngine template;

        public RetryContext(int failCount, Exception exception, RetryEngine template) {
            this.failCount = failCount;
            this.exception = exception;
            this.template = template;
        }
    }


}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 第9章 轻量级线程:协程 《Kotlin极简教程》正式上架: 点击这里 > 去京东商城购买阅读 点击这里 > 去天...
    光剑书架上的书阅读 5,501评论 0 10
  • 早上,因为赖床 跟妈妈拌了嘴; 中午,跟先生一起做了家常面条, 我洗菜,他掌勺, 饭后还手牵手去了屋后的田野消食;...
    小美鱼阅读 1,000评论 0 3
  • 有一种兴奋叫做课上遇到经营型店长,他能听懂你说的内容,他能现身说法更好地助力课堂,他更能真正内化输出自己的专属套路...
    遇见白娘子她妹阅读 1,099评论 0 0
  • 一叶孤飞 2019.1.18 阊阖门开萬户欣, 腊月寒風吹天晴。 晨曦疏竹空中照, 碧泉细涓有鸭群。 雕楼彩墅如玉...
    一叶孤飞阅读 5,135评论 63 36
  • 大家好,我演讲的题目是《传承红色基因,争当双好少年》。 什么是红色文化?虽然我还只是一个孩子,但...
    史倩文阅读 5,548评论 0 0

友情链接更多精彩内容