当前位置: 首页 > 知识库问答 >
问题:

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

穆英飙
2023-08-24

我们有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()); // 所有任务完成后关闭线程池    }

image.png

共有4个答案

聂永怡
2023-08-24

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

futures.add(CompletableFuture.supplyAsync(() -> {            logger.info("开始执行异步线程->>" + s + " 数组下标为:" + i);            //调用接口            //根据接口返回值判断list中的值 是否匹配            //返回处理后的结果            return s + "处理后的结果" + "数组下标:" + i;         }, executorService));
秦渝
2023-08-24
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()); }
微生嘉祥
2023-08-24

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

小牛22978
2023-08-24

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

 类似资料:
  • 问题内容: Java如何确定分配线程或进程的内核?有什么办法可以控制吗?防止两个大线程在同一内核上执行? 基本上,我要问的是有关Java中多线程如何工作或如何在Java中控制它的更多信息。 问题答案: 您不能为特定线程设置处理器关联。但是,如果将程序分为两个进程,则应该能够将这些进程分配给操作系统级别的特定处理器。 http://www.cyberciti.biz/tips/setting-pro

  • 这就是我试图解决但不确定如何解决的问题:我有一个对象数组(假设大小为100),每个对象都有一些id。 有10个线程将从该数组中读取数据并将其插入数据库。 如何确保数据以递增序列的方式根据员工ID的序列插入数据库。例如: 如果数组中的对象具有员工ID 6、8和4,那么这些对象应该按照员工ID 4、6和8在数据库中的顺序插入数据库。如何为此编写多线程代码? 更新:请忽略数据库部分,如果它令人困惑,我的

  • 问题内容: 我尝试从一本书(Paul Hyde,Java Thread Programming)中运行示例。它说线程的顺序将互换。但是我总是得到:之后打印10个“主线程”,然后打印10个“新线程”。更有趣的是:如果我将使用tt.run而不是tt.start,那么结果将相反。也许这本书太老了,示例基于JDK 1.2的原因???代码如下: 问题答案: JVM决定何时将控制权从主线程转移到第二个线程。由

  • 我正在下拉一个充满数据的表,我需要处理这一点,并对每一行进行一点格式化,然后推出一个REST API。 我使用了一个PostgreSQL数据库和Java实现,其思想是将所有数据向下拉,获得行的数量,并向上旋转线程以一次处理一个块。 我已经建立了连接,并将表拉入缓存行集,并使用、和获取行计数。 我正试图找到一种方法,将行集的一大块拆分出来并将其交给处理,但我似乎看不到任何方法可以做到这一点。 有极限

  • 我目前在Java的编程课上学习多线程。根据我的理解,不同线程的执行顺序是无法预测的,因此确保我们实现机制以确保所有东西都按所需的顺序执行是很重要的。 我学到的机制之一是使用,它强制一个线程等待,直到其他线程完成执行。然而,下面的示例代码实际上让我更加困惑: 这段代码应该演示是如何工作的,它将执行,然后得到一个正确打印的。 然而,当我实际运行代码时,执行的顺序似乎仍然是随机的。我得到的结果是 那么,

  • 给定打印字母a-C的三个线程1-3,如何保证输出顺序? 我希望线程的输出是“abcabc”