当你需要不停调用第三方接口,直到返回成功或失败时,可以使用类似的异步重试的机制。以下是一个整合了这个要求的简单示例代码:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class AsyncRetryThirdPartyApi {
private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
public static void main(String[] args) {
// 模拟调用第三方接口
CompletableFuture<String> apiCallResult = callThirdPartyApi();
// 添加重试机制,最多重试3次
CompletableFuture<String> retryFuture = apiCallResult
.thenComposeAsync(result -> {
if ("processing".equals(result)) {
// 如果返回的状态是处理中,进行重试
return retryWithBackoff();
} else {
// 如果是成功或失败状态,则直接返回结果
return CompletableFuture.completedFuture(result);
}
}, executorService);
// 等待异步任务和重试任务完成
String finalResult = retryFuture.join();
System.out.println("Final Result: " + finalResult);
// 关闭线程池
executorService.shutdown();
}
private static CompletableFuture<String> callThirdPartyApi() {
// 模拟调用第三方接口的异步任务
return CompletableFuture.supplyAsync(() -> {
// 模拟第三方接口返回的状态,这里随机生成 "processing", "success", 或 "failure"
double random = Math.random();
if (random < 0.3) {
return "processing";
} else if (random < 0.6) {
return "success";
} else {
return "failure";
}
}, executorService);
}
private static CompletableFuture<String> retryWithBackoff() {
// 使用指数退避(exponential backoff)策略进行重试
int maxRetries = 3;
int retryCount = 0;
long initialDelayMillis = 100; // 初始延迟100毫秒
CompletableFuture<String> retryLoop = new CompletableFuture<>();
retryLoop.completeExceptionally(new RuntimeException("Initial exception")); // 触发初始重试
while (retryCount < maxRetries) {
retryLoop = retryLoop.exceptionally(throwable -> {
// 打印重试信息
System.out.println("Retrying... Attempt " + (retryCount + 1));
// 模拟调用第三方接口的异步任务
return callThirdPartyApi();
}).thenComposeAsync(result -> {
if ("processing".equals(result)) {
// 如果返回的状态仍然是处理中,继续重试
return CompletableFuture.completedFuture(null);
} else {
// 如果是成功或失败状态,则直接返回结果
return CompletableFuture.completedFuture(result);
}
}, executorService);
retryCount++;
initialDelayMillis *= 2; // 每次重试,延迟加倍
try {
TimeUnit.MILLISECONDS.sleep(initialDelayMillis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return retryLoop;
}
}
/
是的,你可以不使用并发框架来实现重试功能,但需要手动处理线程的等待和异步任务。以下是一个简单的例子,使用while循环和Thread.sleep()来实现重试:
public class RetryWithoutConcurrency {
public static void main(String[] args) {
int maxRetries = 3;
int retryCount = 0;
long retryIntervalMillis = 1000; // 重试间隔为1秒
String result = null;
while (retryCount < maxRetries) {
try {
result = callThirdPartyApi();
if ("success".equals(result) || "failure".equals(result)) {
// 如果是成功或失败状态,则退出循环
break;
} else {
System.out.println("Still processing... Retrying after " + retryIntervalMillis + " milliseconds.");
Thread.sleep(retryIntervalMillis);
}
} catch (Exception e) {
System.out.println("Retrying... Attempt " + (retryCount + 1));
}
retryCount++;
}
System.out.println("Final Result: " + result);
}
private static String callThirdPartyApi() {
// 模拟调用第三方接口
double random = Math.random();
if (random < 0.3) {
return "processing";
} else if (random < 0.6) {
return "success";
} else {
return "failure";
}
}
}
在这个例子中,callThirdPartyApi方法模拟了调用第三方接口,而主方法通过while循环进行重试。注意,这里使用了Thread.sleep()来等待一定的时间间隔。请注意,这种方法在某些情况下可能不够灵活,因为它是同步的,可能会导致整个线程阻塞。如果你的应用需要更高的并发性能和灵活性,使用并发框架通常是更好的选择。