Java编写自定义重试工具类的示例代码

 更新时间:2026年01月13日 08:57:40   作者:焰火1999  
这篇文章主要为大家详细介绍了如何基于Java实现自定义重试工具类,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下

Java重试工具类,零依赖。可配置项:接受的异常类型、返回值校验、最大重试次数、重试间隔时间。

1 重试工具类 RetryUtils源码

RetryUtils:

使用了lombok的@Slf4j注解用于打印日志,不用可移除。

import com.example.exception.RetryException;

import lombok.extern.slf4j.Slf4j;

import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * <h2>重试工具类</h2>
 *
 * @author GFire
 * @since 2025/4/22 17:58
 */
@Slf4j
public abstract class RetryUtils {
    /**
     * 失败重试
     *
     * @param task            执行的任务,无返回值
     * @param acceptException 可接受的异常类型,执行的任务抛出此异常(及其子类)则失败重试。null表示不接受任何异常
     * @param maxRetryCount   最大重试次数
     * @param waitTime        重试间隔等待时间, 单位毫秒, <=0则不等待
     * @throws RetryException 如果任务重试超过最大次数、或抛出不可接受的异常,则统一包装抛出RetryException
     */
    public static void doWithRetry(Runnable task, Class<? extends Throwable> acceptException, int maxRetryCount, int waitTime) {
        if (task == null) {
            throw new IllegalArgumentException("task can not be null");
        }

        doWithRetry(() -> {
            task.run();
            return 1;
        }, i -> i == 1, acceptException, maxRetryCount, waitTime);
    }

    /**
     * 失败重试
     *
     * @param task            执行的任务,有返回值
     * @param isValid         判断任务返回值是否合法,不合法则失败重试
     * @param acceptException 可接受的异常类型,执行的任务抛出此异常(及其子类)则失败重试。null表示不接受任何异常
     * @param maxRetryCount   最大重试次数
     * @param waitTime        重试间隔等待时间, 单位毫秒, <=0则不等待
     * @return supplier执行结果
     * @throws RetryException 如果任务重试超过最大次数、或抛出不可接受的异常,则统一包装抛出RetryException
     */
    public static <T> T doWithRetry(Supplier<T> task, Predicate<T> isValid, Class<? extends Throwable> acceptException, int maxRetryCount, int waitTime) {
        if (task == null) {
            throw new IllegalArgumentException("task can not be null");
        }
        if (isValid == null) {
            throw new IllegalArgumentException("isValid can not be null");
        }
        if (maxRetryCount <= 0) {
            throw new IllegalArgumentException("maxRetryCount must be > 0");
        }

        T result = null;
        for (int tryCount = 1; tryCount <= maxRetryCount; tryCount++) {
            try {
                result = task.get();
                if (isValid.test(result)) {
                    return result;
                } else {
                    log.error("result invalid, tryCount: {}, result: {}", tryCount, result);
                }
            } catch (Throwable e) {
                handleException(e, acceptException, maxRetryCount, tryCount);
            }

            if (waitTime > 0 && tryCount < maxRetryCount) {
                sleep(waitTime); // 等待一段时间后重试
            }
        }
        throw new RetryException("result: " + result);
    }

    private static void handleException(Throwable e, Class<? extends Throwable> acceptException, int maxRetryCount, int tryCount) {
        log.error("error, tryCount: {}, Exception: ", tryCount, e);
        if (acceptException != null && acceptException.isInstance(e)) {
            if (tryCount == maxRetryCount) { // 最后一次重试仍失败,则抛出
                throw new RetryException(e);
            }
        } else { // 不可接受的异常,直接抛出
            throw new RetryException(e);
        }
    }

    private static void sleep(int waitTime) {
        try {
            Thread.sleep(waitTime);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RetryException(e);
        }
    }
}

RetryException:

/**
 * <h2>重试异常</h2>
 *
 * @author GFire
 * @since 2025/4/23 11:20
 */
public class RetryException extends RuntimeException {
    public RetryException(String message) {
        super(message);
    }

    public RetryException(Throwable cause) {
        super(cause);
    }
}

2 使用方式

示例1:任务无返回值

 // 模拟调用API接口,失败重试
RetryUtils.doWithRetry(() -> apiService.query(), Exception.class, 3, 2000);

解释:任务apiService.query()无返回值、接受Exception异常、最大重试次数为3、重试间隔2秒

示例2:任务有返回值、需校验返回值

/**
 * 模拟发送通知
 */
public boolean send(String content) {
    try {
        RetryUtils.doWithRetry(() -> noticeService.send(content), this::isValid, Exception.class, 3, 2000);
        return true;
    } catch (RetryException e) {
        log.error("send error: {}", e.toString());
    }
    return false;
}

private boolean isValid(String res) {
    if (StringUtils.isNotEmpty(res)) {
        JSONObject response = JSON.parseObject(res);
        return "ok".equals(response.getString("status"));
    }
    return false;
}

解释:任务noticeService.send(content)有String类型的返回值、isValid方法判断返回值是否合法、接受Exception异常、最大重试次数为3、重试间隔2秒

示例3:任务有返回值、无需校验返回值

RetryUtils.doWithRetry(() -> noticeService.send(), (res) -> true, Exception.class, 3, 2000);

解释:任务noticeService.send()有String类型的返回值、(res) -> true认为任意返回值都合法(即无校验)、接受Exception异常、最大重试次数为3、重试间隔2秒

到此这篇关于Java编写自定义重试工具类的示例代码的文章就介绍到这了,更多相关Java自定义重试内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java实现监听u盘示例分享

    java实现监听u盘示例分享

    这篇文章主要介绍了java实现监听u盘示例,需要的朋友可以参考下
    2014-03-03
  • 一文带你搞懂Java定时器Timer的使用

    一文带你搞懂Java定时器Timer的使用

    定时器类似于我们生活中的闹钟,可以设定一个时间来提醒我们。而定时器是指定一个时间去执行一个任务,让程序去代替人工准时操作。本文就来聊聊Java定时器Timer的使用,需要的可以参考一下
    2023-01-01
  • 利用Java实现简单的词法分析器实例代码

    利用Java实现简单的词法分析器实例代码

    众所周知编译原理中的词法分析算是很重要的一个部分,原理比较简单,不过网上大部分都是用C语言或者C++来编写,因为最近在学习Java,故用Java语言实现了简单的词法分析器。感兴趣的朋友们可以参考借鉴,下面来一起看看吧。
    2016-12-12
  • SpringBoot集成Jasypt敏感信息加密的操作方法

    SpringBoot集成Jasypt敏感信息加密的操作方法

    这篇文章主要介绍了SpringBoot集成Jasypt加密敏感信息,包括敏感信息加密的作用,项目集成Jasypt方式详解,本文给大家介绍的非常详细,需要的朋友可以参考下
    2022-05-05
  • SpringCloud OpenFeign基本介绍与实现示例

    SpringCloud OpenFeign基本介绍与实现示例

    OpenFeign源于Netflix的Feign,是http通信的客户端。屏蔽了网络通信的细节,直接面向接口的方式开发,让开发者感知不到网络通信细节。所有远程调用,都像调用本地方法一样完成
    2023-02-02
  • Spring @RequestMapping 注解及使用技巧详解

    Spring @RequestMapping 注解及使用技巧详解

    @RequestMapping是Spring MVC 中定义请求映射规则的核心注解,用于将HTTP请求映射到Controller处理方法,下面给大家介绍Spring @RequestMapping 注解及使用技巧,感兴趣的朋友一起看看吧
    2025-06-06
  • JAVA内存区域示例详解

    JAVA内存区域示例详解

    Java内存区域包括程序计数器、虚拟机栈、本地方法栈、堆、元空间和直接内存,分别用于线程私有数据和线程共享数据,理解这些区域有助于定位内存问题、优化JVM性能和编写高性能代码,本文介绍java内存区域的相关知识,感兴趣的朋友一起看看吧
    2025-12-12
  • Java实现解出世界最难九宫格问题

    Java实现解出世界最难九宫格问题

    这篇文章主要介绍了Java实现解出世界最难九宫格问题,芬兰数学家因卡拉花费3个月设计出了世界上迄今难度最大的数独游戏,而且它只有一个答案,本文使用Java实现解出,需要的朋友可以参考下
    2015-01-01
  • 一文详解Java中多进程与多线程处理

    一文详解Java中多进程与多线程处理

    在Java编程中,多进程和多线程是两种常见的并发编程技术,用于提高程序的执行效率和响应速度,本文将为大家简单介绍一下多进程与多线程处理的相关知识,希望对大家有所帮助
    2025-01-01
  • 最大子数组和Java实现代码示例

    最大子数组和Java实现代码示例

    这篇文章主要介绍了最大子数组和Java实现的相关资料,文中介绍了两种方法来解决寻找具有最大和的连续子数组的问题,第一种方法是动态规划,第二种方法是分治法,需要的朋友可以参考下
    2024-11-11

最新评论