我试图在循环中调用PUT
请求的rest api。每个调用都是一个CompletableFuture
。每个api调用返回一个类型为RoomType的对象。房间类型
>
我想收集不同列表中的响应(成功和错误响应)。我如何实现这一点?我确信我不能使用
allOf
,因为如果任何一个调用未能更新,它将无法获得所有结果。
如何记录每次呼叫的错误/异常?
public void sendRequestsAsync(Map<Integer, List> map1) {
List<CompletableFuture<Void>> completableFutures = new ArrayList<>(); //List to hold all the completable futures
List<RoomTypes.RoomType> responses = new ArrayList<>(); //List for responses
ExecutorService yourOwnExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
for (Map.Entry<Integer, List> entry :map1.entrySet()) {
CompletableFuture requestCompletableFuture = CompletableFuture
.supplyAsync(
() ->
//API call which returns object of type RoomTypes.RoomType
updateService.updateRoom(51,33,759,entry.getKey(),
new RoomTypes.RoomType(entry.getKey(),map2.get(entry.getKey()),
entry.getValue())),
yourOwnExecutor
)//Supply the task you wanna run, in your case http request
.thenApply(responses::add);
completableFutures.add(requestCompletableFuture);
}
用于要使用For循环的位置。这是一个可行的解决办法。完全uture.all
您希望下载一个网站的100个不同网页的内容。您可以按顺序执行此操作,但这将花费大量时间。因此,可以编写一个函数来获取网页链接,并返回一个完整的未来:
CompletableFuture<String> downloadWebPage(String pageLink) {
return CompletableFuture.supplyAsync(() -> {
// Code to download and return the web page's content
});
}
在循环中调用上一个函数,我们使用的是JAVA 8
List<String> webPageLinks = Arrays.asList(...) // A list of 100 web page links
// Download contents of all the web pages asynchronously
List<CompletableFuture<String>> pageContentFutures = webPageLinks.stream()
.map(webPageLink -> downloadWebPage(webPageLink))
.collect(Collectors.toList());
// Create a combined Future using allOf()
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
pageContentFutures.toArray(new CompletableFuture[pageContentFutures.size()])
);
未来的问题。allOf()是指它返回CompletableFuture。但是,通过编写几行额外的代码,我们可以得到所有包装的CompletableFutures的结果
// When all the Futures are completed, call `future.join()` to get their results and collect the results in a list -
CompletableFuture<List<String>> allPageContentsFuture = allFutures.thenApply(v -> {
return pageContentFutures.stream()
.map(pageContentFuture -> pageContentFuture.join())
.collect(Collectors.toList());
});
现在让我们统计包含关键字的网页数量-
// Count the number of web pages having the "CompletableFuture" keyword.
CompletableFuture<Long> countFuture = allPageContentsFuture.thenApply(pageContents -> {
return pageContents.stream()
.filter(pageContent -> pageContent.contains("CompletableFuture"))
.count();
});
System.out.println("Number of Web Pages having CompletableFuture keyword - " +
countFuture.get());
或者,也许您可以从不同的角度处理这个问题,而不是强制使用CompletableFuture
,您可以使用CompletionService。
CompletionService
的整体思想是,一旦给定未来的答案准备就绪,它就会被放入一个队列中,您可以从中使用结果。
备选方案1:没有可完成的未来
CompletionService<String> cs = new ExecutorCompletionService<>(executor);
List<Future<String>> futures = new ArrayList<>();
futures.add(cs.submit(() -> "One"));
futures.add(cs.submit(() -> "Two"));
futures.add(cs.submit(() -> "Three"));
futures.add(cs.submit(() -> { throw new RuntimeException("Sucks to be four"); }));
futures.add(cs.submit(() -> "Five"));
List<String> successes = new ArrayList<>();
List<String> failures = new ArrayList<>();
while (futures.size() > 0) {
Future<String> f = cs.poll();
if (f != null) {
futures.remove(f);
try {
//at this point the future is guaranteed to be solved
//so there won't be any blocking here
String value = f.get();
successes.add(value);
} catch (Exception e) {
failures.add(e.getMessage());
}
}
}
System.out.println(successes);
System.out.println(failures);
这将产生:
[One, Two, Three, Five]
[java.lang.RuntimeException: Sucks to be four]
备选方案2:具有完全的未来
但是,如果您真的需要处理CompletableFuture
,您也可以将它们提交给完成服务,只需将它们直接放入队列:
例如,以下变化具有相同的结果:
BlockingQueue<Future<String>> tasks = new ArrayBlockingQueue<>(5);
CompletionService<String> cs = new ExecutorCompletionService<>(executor, tasks);
List<Future<String>> futures = new ArrayList<>();
futures.add(CompletableFuture.supplyAsync(() -> "One"));
futures.add(CompletableFuture.supplyAsync(() -> "Two"));
futures.add(CompletableFuture.supplyAsync(() -> "Three"));
futures.add(CompletableFuture.supplyAsync(() -> { throw new RuntimeException("Sucks to be four"); }));
futures.add(cs.submit(() -> "Five"));
//places all futures in completion service queue
tasks.addAll(futures);
List<String> successes = new ArrayList<>();
List<String> failures = new ArrayList<>();
while (futures.size() > 0) {
Future<String> f = cs.poll();
if (f != null) {
futures.remove(f);
try {
//at this point the future is guaranteed to be solved
//so there won't be any blocking here
String value = f.get();
successes.add(value);
} catch (Exception e) {
failures.add(e.getMessage());
}
}
}
您可以简单地使用allOf()
获得一个在所有初始期货都完成(异常或非异常)时完成的期货,然后使用收集器在成功和失败之间分割它们。分区依据()
:
List<CompletableFuture<RoomTypes.RoomType>> completableFutures = new ArrayList<>(); //List to hold all the completable futures
ExecutorService yourOwnExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
for (Map.Entry<Integer, List> entry : map1.entrySet()) {
CompletableFuture<RoomTypes.RoomType> requestCompletableFuture = CompletableFuture
.supplyAsync(
() ->
//API call which returns object of type RoomTypes.RoomType
updateService.updateRoom(51, 33, 759, entry.getKey(),
new RoomTypes.RoomType(entry.getKey(), map2.get(entry.getKey()),
entry.getValue())),
yourOwnExecutor
);
completableFutures.add(requestCompletableFuture);
}
CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0]))
// avoid throwing an exception in the join() call
.exceptionally(ex -> null)
.join();
Map<Boolean, List<CompletableFuture<RoomTypes.RoomType>>> result =
completableFutures.stream()
.collect(Collectors.partitioningBy(CompletableFuture::isCompletedExceptionally)));
结果映射将包含一个带有true
的条目用于失败的期货,另一个带有false
键的条目用于成功的期货。然后,您可以检查这两个条目以采取相应的行动。
请注意,与原始代码相比,有2处轻微更改:
请求完全未来
现在是一个完全未来关于日志记录/异常处理,只需添加相关的请求复杂uture.handle()
来单独记录它们,但保留请求复杂未来
,而不是由处理()
产生的。
我正在使用Volley向API发出GET请求: 预期的JSON对象响应很大(可能高达500 KB)。我无法在日志中看到完整的响应。仅显示前50行左右。我还得到了info: BasicNetwork.log慢速请求:请求的HTTP响应= 这意味着请求需要超过3000毫秒。 尝试过的事情: 我已经在手机的开发者选项中将记录器缓冲区大小增加到1M。 原因可能是什么?当它很大的时候,响应是大块发送的吗?如
我想要一个完整的未来,只发出完成的信号(例如,我没有返回值)。 我可以将CompletableFuture实例化为: 但是我应该向完整的方法提供什么呢?例如,我不能做
下面是我的父组件,它包含一个循环的多个输入。如何选择一个来聚焦?在这种情况下,我必须创建动态吗?
我正在创建一个报告,并已经自动化了抓取图像并将其放入的过程。它正在工作,但比它需要的时间要长。我希望有人能帮我实现一个循环来简化代码。 我尝试了几种方法,但当涉及到放置图像的区域时,它似乎总是默认为我设置的初始变量。 DS1=rng&“a.jpg” DS1_1=左(DS1,6)&“00-”&Mid(DS1,4,3)&“99” DS1_2=左(DS1,8) 在错误转到DS3 时,设置shp=acti
有一个名为Avro-Tools的工具,它随Avro一起提供,可以用来在JSON、Avro-Schema(.avsc)和二进制格式之间进行转换。但它不能用于循环引用。 我们有两个文件: > 循环.avsc(由Avro生成) json(由jackson生成,因为它有循环引用,Avro不喜欢这样)。 通告.AVSC circular.json 在上面运行avro-tools的命令 Java-jar av