美文网首页
重试机制(可限制最大重试次数和最大重试时间)

重试机制(可限制最大重试次数和最大重试时间)

作者: 一只狗被牵着走 | 来源:发表于2019-08-26 15:53 被阅读0次

重试抽象类 RetryTemplate.class

package com.test.demo.core.service.template;

import com.test.common.logging.Logger;
import com.test.common.logging.LoggerFactory;
import com.test.demo.common.util.log.LoggerConstants;
import com.test.demo.common.util.log.LoggerUtil;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.FutureTask;

public abstract class RetryTemplate {

    private static final int DEFAULT_RETRY_TIME = 1;

    private int retryTime = DEFAULT_RETRY_TIME;

    private static final Logger LOGGER = LoggerFactory.getLogger(RetryTemplate.class);

    /**
     * 重试的睡眠时间,毫秒
     */
    private int sleepTime = 0;

    public int getSleepTime() {
        return sleepTime;
    }

    public RetryTemplate setSleepTime(int sleepTime) {
        if(sleepTime < 0) {
            throw new IllegalArgumentException("sleepTime should equal or bigger than 0");
        }

        this.sleepTime = sleepTime;
        return this;
    }

    public int getRetryTime() {
        return retryTime;
    }

    public RetryTemplate setRetryTime(int retryTime) {
        if (retryTime <= 0) {
            throw new IllegalArgumentException("retryTime should bigger than 0");
        }

        this.retryTime = retryTime;
        return this;
    }

    /**
     * 重试的业务执行代码
     * 失败时请抛出一个异常
     *
     * 确定返回的封装类,根据返回结果的状态来判定是否需要重试,doBiz方法抛出异常时重试,直到重试次数使用完或不再抛出异常
     *
     * @return Object
     */
    protected abstract Object doBiz() throws Exception;


    public Object execute() throws InterruptedException {
        for (int i = 0; i < retryTime; i++) {
            try {
                return doBiz();
            } catch (Exception e) {
                LoggerUtil.error(LoggerConstants.ERROR_LOGGER, e, "系统异常,第 " + (i + 1) + " 次重试失败");
                Thread.sleep(sleepTime);
            }
        }

        return null;
    }


    public FutureTask<Object> submit(ExecutorService executorService) {
        if (executorService == null) {
            throw new IllegalArgumentException("please choose executorService!");
        }

        FutureTask<Object> futureTask = new FutureTask<Object>(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                LoggerUtil.info(LOGGER, "Asynchronous Callable");
                // 开始执行业务逻辑
                for (int i = 0; i < retryTime; i++) {
                    try {
                        return doBiz();
                    } catch (Exception e) {
                        LoggerUtil.error(LoggerConstants.ERROR_LOGGER, e, "系统异常,第 " + (i + 1) + " 次重试失败");
                        Thread.sleep(sleepTime);
                    }
                }
                return null;
            }
        });
        return futureTask;
    }

}

用例演示伪代码:

final ExecutorService exec = Executors.newFixedThreadPool(1);
FutureTask<Object> futureTask = new RetryTemplate() {
    @Override
    protected Result doBiz() throws Exception {
        // 执行业务逻辑,上抛异常触发重试
        Result  result = do();
        if (condition) {
            throw new Exception("获取result为空");
        }
        return result;
    }
// 重试次数 2000 次, 每次重试间隔 5 毫秒
}.setRetryTime(2000).setSleepTime(5).submit(exec);

// 执行线程
exec.submit(futureTask);


Result  result = new Result();
try {
    // 限时 1 s,超过1s,终止重试
    result = (Result) futureTask.get(1000 * 1, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
    // 关闭线程池
    exec.shutdown();
    LoggerUtil.error(LoggerConstants.BIZ_SERVICE_IMPL, "[ time limit task] timeout", e);
} catch (Exception e) {
    LoggerUtil.error(LoggerConstants.BIZ_SERVICE_IMPL, "[ time limit task] end-failed", e);
} finally {
    // 关闭线程池
    if (exec != null) {
        exec.shutdown();
    }
}
// result即为最终执行结果
return result;

相关文章

网友评论

      本文标题:重试机制(可限制最大重试次数和最大重试时间)

      本文链接:https://www.haomeiwen.com/subject/gdqdectx.html