返回URL首个结果

之前遇到一个需求,是需要请求区块链上面的block数据,进行数据解析然后入库存储,因为block产生一定时间后的数据都是固定的,链接不止一个,但返回的结果都是一样的,我只需要拿到首个返回的结果就好了,如果你也类似的场景,这篇文章或许能给你到参考

工具类

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;
    }
}

结果演示

可以看到还没有请求完,其实结果就已经返回来了

猜你喜欢

转载自blog.csdn.net/itjavaee/article/details/108822018
今日推荐