I encountered a requirement before, which was to request the block data on the blockchain, analyze the data and store it in the database, because the data after a certain period of time after the block is generated is fixed, and there is more than one link, but the results returned are all the same , I only need to get the first returned result. If you have a similar scenario, this article may give you a reference
Tools
package com.yianjia.common.utils;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
/**
* @author z
*/
@Component
public class FastFirstRequestUtils {
private static final Logger logger = LoggerFactory.getLogger(FastFirstRequestUtils.class);
private List<String> urlList = Arrays.asList(
"https://www.baidu.com",
"https://www.baidu.com",
"https://www.baidu.com",
"https://www.baidu.com",
"https://www.baidu.com"
);
private static ExecutorService executorService = new ThreadPoolExecutor(0, 128, 0L, TimeUnit.SECONDS, new SynchronousQueue<>(), (new ThreadFactoryBuilder()).setNameFormat("get_url-1-%d").build());
@Autowired
private RestTemplateUtils restTemplateUtils;
@PostConstruct
public void run() {
CompletableFuture[] futures = this.urlList.stream().map((url) -> CompletableFuture.supplyAsync(() -> {
// 替换成你自己的请求
String getBlockResult = this.restTemplateUtils.exchange(url, HttpMethod.POST, null, null, null, String.class);
return getBlockResult;
}, executorService).exceptionally((e) -> null)).toArray((size) -> new CompletableFuture[size]);
// n 为完成数,只要完成数达到,就会返回结果集,不会阻塞
CompletableFuture completableFuture = firstSuccessful(Arrays.asList(futures), 1);
List<String> resultList = null;
try {
resultList = (List) completableFuture.get(5L, TimeUnit.SECONDS);
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
} catch (ExecutionException executionException) {
executionException.printStackTrace();
} catch (TimeoutException timeoutException) {
timeoutException.printStackTrace();
}
if (null != resultList && 0 != resultList.size()) {
System.out.println("-------------------结果出来啦-------------------");
System.out.println(resultList.get(0));
System.out.println("-------------------结果出来啦-------------------");
}
}
/**
* @param list 任务集
* @param n 需要完成的任务数
* @param <T>
* @return
*/
private static <T> CompletableFuture<List<T>> firstSuccessful(List<CompletableFuture<T>> list, int n) {
int maxFail = list.size() - n;
if (maxFail < 0 || n <= 0) {
throw new IllegalArgumentException();
}
AtomicInteger counter = new AtomicInteger(1);
AtomicInteger fails = new AtomicInteger(0);
List<T> rList = new ArrayList(n);
CompletableFuture<List<T>> result = new CompletableFuture();
BiConsumer<T, Throwable> c = (value, failure) -> {
if (n != rList.size()) {
if (failure != null) {
if (fails.incrementAndGet() > maxFail) {
result.completeExceptionally(failure);
}
} else if (!result.isDone()) {
boolean commit = false;
synchronized (rList) {
if (null != value) {
commit = rList.size() < n && rList.add(value) && rList.size() == n;
}
}
if (commit) {
result.complete(Collections.unmodifiableList(rList));
return;
}
}
if (counter.get() == list.size()) {
result.complete(Collections.unmodifiableList(rList));
} else {
counter.incrementAndGet();
}
}
};
for (CompletableFuture<T> tCompletableFuture : list) {
CompletableFuture f = tCompletableFuture;
f.whenComplete(c);
}
return result;
}
}
Result presentation
You can see that the request has not been completed yet, but the result has already been returned