加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 如何处理多个ListenableFutures? (弹簧)

发布时间:2020-12-15 04:33:22 所属栏目:Java 来源:网络整理
导读:我正在编写一个控制器,我需要让它异步.我该如何处理ListenableFuture列表?因为我有一个URL列表,我需要逐个发送GET请求,它的最佳解决方案是什么? @RequestMapping(value = "/repositories",method = RequestMethod.GET) private void getUsername(@RequestP
我正在编写一个控制器,我需要让它异步.我该如何处理ListenableFuture列表?因为我有一个URL列表,我需要逐个发送GET请求,它的最佳解决方案是什么?

@RequestMapping(value = "/repositories",method = RequestMethod.GET)
    private void getUsername(@RequestParam(value = "username") String username) {
        System.out.println(username);
        List<ListenableFuture> futureList = githubRestAsync.getRepositoryLanguages(username);
        System.out.println(futureList.size());
}

在服务中我使用List< ListanbleFuture>这似乎不起作用,因为它是异步的,在控制器方法中我不能使用futureList的大小来为回调运行for循环.

public List<ListenableFuture> getRepositoryLanguages(String username){
      return getRepositoryLanguages(username,getUserRepositoriesFuture(username));
    }

private ListenableFuture getUserRepositoriesFuture(String username) throws HttpClientErrorException {
        HttpEntity entity = new HttpEntity(httpHeaders);
        ListenableFuture future = restTemplate.exchange(githubUsersUrl + username + "/repos",HttpMethod.GET,entity,String.class);
        return future;
    }
private List<ListenableFuture> getRepositoryLanguages(final String username,ListenableFuture<ResponseEntity<String>> future) {
        final List<ListenableFuture> futures = new ArrayList<>();
        future.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {
            @Override
            public void onSuccess(ResponseEntity<String> response) {
                ObjectMapper mapper = new ObjectMapper();
                try {
                    repositories = mapper.readValue(response.getBody(),new TypeReference<List<Repositories>>() {
                    });
                    HttpEntity entity = new HttpEntity(httpHeaders);
                    System.out.println("Repo size: " + repositories.size());
                    for (int i = 0; i < repositories.size(); i++) {
                        futures.add(restTemplate.exchange(githubReposUrl + username + "/" + repositories.get(i).getName() + "/languages",String.class));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            @Override
            public void onFailure(Throwable throwable) {
                System.out.println("FAILURE in getRepositoryLanguages: " + throwable.getMessage());
            }
        });

        return futures;
    }

我应该使用像ListenableFuture< List>这样的东西吗?而不是List< ListenableFuture> ?

解决方法

您似乎有一个List< ListenableFuture< Result>>,但您需要一个ListenableFuture< List< Result>>,因此您可以在所有期货完成时执行一个操作.

public static <T> ListenableFuture<List<T>> allOf(final List<? extends ListenableFuture<? extends T>> futures) {
    // we will return this ListenableFuture,and modify it from within callbacks on each input future
    final SettableListenableFuture<List<T>> groupFuture = new SettableListenableFuture<>();

    // use a defensive shallow copy of the futures list,to avoid errors that could be caused by
    // someone inserting/removing a future from `futures` list after they call this method
    final List<? extends ListenableFuture<? extends T>> futuresCopy = new ArrayList<>(futures);

    // Count the number of completed futures with an AtomicInt (to avoid race conditions)
    final AtomicInteger resultCount = new AtomicInteger(0);
    for (int i = 0; i < futuresCopy.size(); i++) {
        futuresCopy.get(i).addCallback(new ListenableFutureCallback<T>() {
            @Override
            public void onSuccess(final T result) {
                int thisCount = resultCount.incrementAndGet();

                // if this is the last result,build the ArrayList and complete the GroupFuture
                if (thisCount == futuresCopy.size()) {
                   List<T> resultList = new ArrayList<T>(futuresCopy.size());
                    try {
                        for (ListenableFuture<? extends T> future : futuresCopy) {
                            resultList.add(future.get());
                        }
                        groupFuture.set(resultList);
                    } catch (Exception e) {
                        // this should never happen,but future.get() forces us to deal with this exception.
                        groupFuture.setException(e);
                    }
                }
            }

            @Override
            public void onFailure(final Throwable throwable) {
                groupFuture.setException(throwable);

                // if one future fails,don't waste effort on the others
                for (ListenableFuture future : futuresCopy) {
                    future.cancel(true);
                }
            }
        });
    }

    return groupFuture;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读