Java 开源重试类 guava-retrying 使用案例

使用背景

需要重复尝试执行某些动作,guava-retrying 提供了成型的重试框架

依赖

xml 复制代码
        <dependency>
            <groupId>com.github.rholder</groupId>
                <artifactId>guava-retrying</artifactId>
            <version>${retrying.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>com.google.guava</groupId>
                    <artifactId>guava</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

${retrying.version} 实际为 2.0.0

如果已有 guava 缓存框架引入则可以像上面一样去除,否则可以保留

定义工具类

java 复制代码
import com.github.rholder.retry.Attempt;
import com.github.rholder.retry.RetryListener;
import com.github.rholder.retry.Retryer;
import com.github.rholder.retry.RetryerBuilder;
import com.github.rholder.retry.StopStrategies;
import com.github.rholder.retry.StopStrategy;
import com.github.rholder.retry.WaitStrategies;
import com.google.common.base.Predicate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.StopWatch;

import java.text.MessageFormat;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

@Slf4j
public class RetryUtil {

    private RetryUtil(){}

    /**
     * 根据输入的condition重复做task,在规定的次数内达到condition则返回,
     * 如果超过retryTimes则返回null, 重试次数,整个重试时间以及retry exception都会记录log
     * 需要注意调用的时候需要新起一个线程,不然重试失败会阻塞当前线程
     *
     * @param condition  重试条件,比如接口返回errorCode为处理中,或不是最终需要的结果
     * @param task       重试做的任务
     * @param sleepTime  重试间隔时间,单位毫秒
     * @param retryTimes 最大重试次数
     * @return targetBean
     */
    public static <V> Optional<V> retry(Predicate<V> condition, Callable<V> task, int sleepTime, Integer retryTimes) {
        Optional<V> result = Optional.empty();
        StopStrategy stopStrategy = null;
        if (retryTimes == null) {
            stopStrategy = StopStrategies.neverStop();
        } else {
            stopStrategy = StopStrategies.stopAfterAttempt(retryTimes);
        }
        StopWatch stopWatch = new StopWatch();
        try {
            stopWatch.start();
            Retryer<V> retry = RetryerBuilder.<V>newBuilder()
                    // 默认任务执行过程中发生异常自动重试
                    .retryIfException()
                    // 重试条件(按照业务场景)
                    .retryIfResult(condition)
                    // 等待策略
                    .withWaitStrategy(WaitStrategies.fixedWait(sleepTime, TimeUnit.MILLISECONDS))
                    // 重试策略
                    .withStopStrategy(stopStrategy)
                    // 重试监听器
                    .withRetryListener(new RetryListener() {
                        @Override
                        public <V> void onRetry(Attempt<V> attempt) {
                            // 记录重试次数和异常信息
                            log.info(MessageFormat.format("{0}th retry", attempt.getAttemptNumber()));
                            if (attempt.hasException()) {
                                log.error(MessageFormat.format("retry exception:{0}", attempt.getExceptionCause()));
                            }
                        }
                    }).build();

            // 开始执行重试任务
            result = Optional.ofNullable(retry.call(task));
        } catch (Exception e) {
            log.error("retry fail:", e);
        } finally {
            stopWatch.stop();
            log.info("retry execute time" + stopWatch.getTime());
        }
        return result;
    }
}

实际使用

java 复制代码
    private void xxxxXxxxx() {
        Predicate<Boolean> condition = result -> result;
        RetryUtil.retry(condition::test,
                () -> xxxxxxService.xxxxXxxx(),
                60000,
                60);
    }

其中 xxxxxxService.xxxxXxxx() : 方法为要重试的内容,同时改方法要返回

条件的指定类型。

第一个为入参为重试条件。

60000 代表重试时间间隔,单位 毫秒

60 标识重试次数

相关推荐
wxin_VXbishe10 分钟前
springboot居家养老管理系统-计算机毕业设计源码55953
java·c++·spring boot·python·spring·django·php
互亿无线明明12 分钟前
国际金融短信:如何为跨境金融业务构建稳定安全的消息通知链路?
java·python·安全·eclipse·django·virtualenv·pygame
Json_12 分钟前
springboot框架 线程池使用与配置,简单粗暴直接用,再也不用自己创建线程了~
java·spring boot·后端
_半夏曲18 分钟前
maven多依赖,由于包路径一样,导致引入类错乱
java·maven
前端小张同学23 分钟前
餐饮小程序需要你们
java·前端·后端
二十雨辰26 分钟前
[SSM]Spring快速入门
java·spring
豆约翰30 分钟前
Z字形扫描ccf
java·开发语言·算法
闲人编程35 分钟前
权限系统设计与RBAC实现
java·网络·数据库·rbac·权限·codecapsule
nbsaas-boot36 分钟前
JWT 与 Session 的实用场景分析:从架构边界到工程落地
java·开发语言·架构
Tim_1036 分钟前
【C++入门】03、C++整型
java·开发语言·jvm