Java實現(xiàn)自定義重試工具類
Spring-retry、guava的Retry都提供有重試工具,但二者均存在一個確缺點,即如果重試等待過程中會一直阻塞工作線程,這對于在生產(chǎn)環(huán)境使用是存在風險的,如果存在大量長時間等待的重試任務將會耗盡系統(tǒng)線程資源,下文基于線程池來完成一個簡易的重試工具類。
核心思想
將任務封裝為一個task,將任務的重試放入可調(diào)度的線程池中完成執(zhí)行,避免在重試間隔中,線程陷入無意義的等待,同時將重試機制抽象為重試策略。
代碼實現(xiàn)
重試工具類
package com.huakai.springenv.retry.v2; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @Slf4j public class RetryUtil { public static ExecutorService EXECUTOR = Executors.newFixedThreadPool(1); private static final ScheduledExecutorService SCHEDULER_EXECUTOR = Executors.newScheduledThreadPool(20); /** * 任務重試 * @param actualTaskFunction 執(zhí)行的任務函數(shù) * @param resultHandler 任務結果處理器 * @param maxRetry 最大重試次數(shù) * @param retryStrategy 重試策略 */ public static void retryTask( Function<Integer, String> actualTaskFunction, Function<String, Boolean> resultHandler, int maxRetry, RetryStrategy retryStrategy // 使用策略模式 ) { Runnable runnable = new Runnable() { final AtomicInteger retryCount = new AtomicInteger(); // 當前重試次數(shù) final AtomicInteger maxRetryCount = new AtomicInteger(maxRetry); // 最大重試次數(shù) @Override public void run() { String taskResult = actualTaskFunction.apply(retryCount.get()); // 執(zhí)行任務 Boolean taskSuccess = resultHandler.apply(taskResult); // 處理任務結果 if (taskSuccess) { if (retryCount.get() > 1) { log.info("任務重試成功,重試次數(shù):{}", retryCount.get()); } return; // 任務成功,不需要再重試 } if (retryCount.incrementAndGet() == maxRetryCount.get()) { log.warn("任務重試失敗,重試次數(shù):{}", retryCount.get()); return; // 達到最大重試次數(shù),停止重試 } // 獲取重試間隔 long delay = retryStrategy.getDelay(retryCount.get()); TimeUnit timeUnit = retryStrategy.getTimeUnit(retryCount.get()); // 安排下次重試 SCHEDULER_EXECUTOR.schedule(this, delay, timeUnit); log.info("任務重試失敗,等待 {} {} 后再次嘗試,當前重試次數(shù):{}", delay, timeUnit, retryCount.get()); } }; EXECUTOR.execute(runnable); // 執(zhí)行任務 } public static void main(String[] args) { // 使用指數(shù)退避重試策略 RetryStrategy retryStrategy = new ExponentialBackoffRetryStrategy(1, TimeUnit.SECONDS); retryTask( retryCount -> "task result", taskResult -> Math.random() < 0.1, 5, retryStrategy ); } }
重試策略
指數(shù)退避
package com.huakai.springenv.retry.v2; import java.util.concurrent.TimeUnit; /** * 指數(shù)退避重試策略 */ public class ExponentialBackoffRetryStrategy implements RetryStrategy { private final long initialDelay; private final TimeUnit timeUnit; public ExponentialBackoffRetryStrategy(long initialDelay, TimeUnit timeUnit) { this.initialDelay = initialDelay; this.timeUnit = timeUnit; } @Override public long getDelay(int retryCount) { return (long) (initialDelay * Math.pow(2, retryCount - 1)); // 指數(shù)退避 } @Override public TimeUnit getTimeUnit(int retryCount) { return timeUnit; } }
自定義重試間隔時間
package com.huakai.springenv.retry.v2; import java.util.List; import java.util.concurrent.TimeUnit; /** * 自定義重試間隔時間的重試策略 */ public class CustomerIntervalRetryStrategy implements RetryStrategy { // 配置重試間隔和時間單位 List<RetryInterval> retryIntervals; public CustomerIntervalRetryStrategy(List<RetryInterval> retryIntervals) { this.retryIntervals = retryIntervals; } @Override public long getDelay(int retryCount) { return retryIntervals.get(retryCount).getDelay(); } @Override public TimeUnit getTimeUnit(int retryCount){ return retryIntervals.get(retryCount).getTimeUnit(); } }
固定間隔
package com.huakai.springenv.retry.v2; import java.util.concurrent.TimeUnit; /** * 固定間隔重試策略 */ public class FixedIntervalRetryStrategy implements RetryStrategy { private final long interval; private final TimeUnit timeUnit; public FixedIntervalRetryStrategy(long interval, TimeUnit timeUnit) { this.interval = interval; this.timeUnit = timeUnit; } @Override public long getDelay(int retryCount) { return interval; } @Override public TimeUnit getTimeUnit(int retryCount) { return timeUnit; } }
到此這篇關于Java實現(xiàn)自定義重試工具類的文章就介紹到這了,更多相關Java重試工具類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
淺析打開eclipse出現(xiàn)Incompatible JVM的解決方法
本篇文章是對打開eclipse出現(xiàn)Incompatible JVM的解決方法進行了詳細的分析介紹,需要的朋友參考下2013-07-07