Java 多线程执行处理,利用CompletableFuturer如何保证顺序?

我们有1000多条数据,请求1000次第三方个接口, 效率很是低下! 所以我想利用多线程的方式快速的调用完这1000次接口请求并处理响应
但是有个问题,线程是在for循环中执行的,调用顺序肯定是错乱的,这就导致接调用后 返回的结果肯定和List中的不匹配了··· 这种情况怎么能保证顺序呢?这是我的代码

public static void main(String[] args) {

List<String> list=new ArrayList<>();

for (int i = 0; i < 20; i++) {

list.add("数据"+i);

}

int maximumPoolSize = MAX_POOL_THREAD + 1; //最大线程数 = CPU核数+1(计算密集型)

ExecutorService executorService = new ThreadPoolExecutor(MAX_POOL_THREAD, maximumPoolSize, 60, TimeUnit.SECONDS,

new LinkedBlockingQueue<>(maximumPoolSize * 2), new ThreadPoolExecutor.CallerRunsPolicy());

CompletableFuture[] futures = new CompletableFuture[list.size()];

for (int i = 0; i < list.size(); i++) {

String s = list.get(i);

logger.info("线程执行前"+s);

int finalI = i;

futures[i]= CompletableFuture.runAsync(() -> {

logger.info("开始执行异步线程->>"+s);

//调用接口

//根据接口返回值判断list中的值 是否匹配 问题是返回肯定和List的值不不配····

}, executorService); // 用自定义线程池

}

// 所有请求完成后处理逻辑

CompletableFuture.allOf(futures).thenRun(() -> {

logger.info("线程执行完毕:{}",JSON.toJSONString(futures));

//调用发送短信

}).thenRun(() -> executorService.shutdown()); // 所有任务完成后关闭线程池

}


回答:

public static void main(String[] args) {

List<String> list = new ArrayList<>();

for (int i = 0; i < 20; i++) {

list.add("数据" + i);

}

int maximumPoolSize = MAX_POOL_THREAD + 1; //最大线程数 = CPU核数+1(计算密集型)

ExecutorService executorService = new ThreadPoolExecutor(MAX_POOL_THREAD, maximumPoolSize, 60, TimeUnit.SECONDS,

new LinkedBlockingQueue<>(maximumPoolSize * 2), new ThreadPoolExecutor.CallerRunsPolicy());

List<CompletableFuture<String>> futures = new ArrayList<>();

for (int i = 0; i < list.size(); i++) {

String s = list.get(i);

logger.info("线程执行前" + s);

futures.add(CompletableFuture.supplyAsync(() -> {

logger.info("开始执行异步线程->>" + s);

//调用接口

//根据接口返回值判断list中的值 是否匹配

//返回处理后的结果

return s + "处理后的结果";

}, executorService)); // 用自定义线程池

}

// 所有请求完成后处理逻辑

CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenRun(() -> {

List<String> results = futures.stream().map(CompletableFuture::join).collect(Collectors.toList());

logger.info("线程执行完毕:{}", JSON.toJSONString(results));

//调用发送短信

}).thenRun(() -> executorService.shutdown());

}


回答:

多线程执行无法保证线程之间的执行顺序,但是可以把数组下标也带到线程中去,这样就可以知道接口返回的值是对应哪个数组下标的了

futures.add(CompletableFuture.supplyAsync(() -> {

logger.info("开始执行异步线程->>" + s + " 数组下标为:" + i);

//调用接口

//根据接口返回值判断list中的值 是否匹配

//返回处理后的结果

return s + "处理后的结果" + "数组下标:" + i;

}, executorService));


回答:

既然并发那就肯定不能保证有序的啊,也许你需要的是第几个请求返回应该和第几个数据做判断,而不是保证有序


回答:

futures第i个元素和list第i个元素不是对应吗?

以上是 Java 多线程执行处理,利用CompletableFuturer如何保证顺序? 的全部内容, 来源链接: utcz.com/p/945318.html

回到顶部