如何在Kotlin中通过参数配置超时与最大重试时长实现重试?
实现支持动态参数的重试功能
原有的注解式重试(如@Retry(retryInterval = 60))依赖编译期确定的常量值,无法满足调用者动态传入最大重试时长和重试间隔的需求。这里推荐用高阶函数封装重试逻辑,这是Kotlin中实现此类动态控制逻辑的常规方案,既保证复用性,又能灵活接收调用者参数。
基础实现(阻塞式)
封装一个通用的重试函数,接收重试参数和目标执行逻辑:
fun <T> retryWithDynamicParams( maxRetryDurationMs: Long, retryIntervalMs: Long, block: () -> T ): T { val startTime = System.currentTimeMillis() var lastException: Exception? = null while (System.currentTimeMillis() - startTime < maxRetryDurationMs) { try { // 执行目标逻辑,成功则直接返回结果 return block() } catch (e: Exception) { lastException = e // 等待重试间隔后继续循环 Thread.sleep(retryIntervalMs) } } // 超时后抛出最后一次异常,或自定义异常 throw lastException ?: RuntimeException("重试超时,未执行成功") }
调用示例
// 调用时传入动态参数:最大重试3秒,每次间隔500毫秒 val result = retryWithDynamicParams(3000, 500) { doSomething(args) }
进阶优化
1. 自定义重试异常范围
默认会捕获所有异常并重试,可添加参数控制仅对特定异常重试:
fun <T> retryWithDynamicParams( maxRetryDurationMs: Long, retryIntervalMs: Long, retryOn: (Exception) -> Boolean = { true }, // 默认所有异常都重试 block: () -> T ): T { val startTime = System.currentTimeMillis() var lastException: Exception? = null while (System.currentTimeMillis() - startTime < maxRetryDurationMs) { try { return block() } catch (e: Exception) { if (retryOn(e)) { lastException = e Thread.sleep(retryIntervalMs) } else { // 不满足重试条件,直接抛出异常 throw e } } } throw lastException ?: RuntimeException("重试超时,未执行成功") } // 调用示例:仅对IO异常重试 val result = retryWithDynamicParams(3000, 500, { it is IOException }) { doSomething(args) }
2. 协程版本(非阻塞)
如果项目用Kotlin协程,可替换Thread.sleep为delay,避免阻塞线程:
import kotlinx.coroutines.delay import kotlinx.coroutines.coroutineScope suspend fun <T> retryWithDynamicParamsCoroutine( maxRetryDurationMs: Long, retryIntervalMs: Long, retryOn: (Exception) -> Boolean = { true }, block: suspend () -> T ): T = coroutineScope { val startTime = System.currentTimeMillis() var lastException: Exception? = null while (System.currentTimeMillis() - startTime < maxRetryDurationMs) { try { return@coroutineScope block() } catch (e: Exception) { if (retryOn(e)) { lastException = e delay(retryIntervalMs) } else { throw e } } } throw lastException ?: RuntimeException("重试超时,未执行成功") }
这种高阶函数的方式比零散写while循环更易维护,也能在多个地方复用重试逻辑,是业内处理动态重试需求的常规做法。
内容的提问来源于stack exchange,提问作者Kevin2566
相关产品推荐
相关产品推荐

