关于使用CompletableFuture的建议

问题描述 投票:0回答:2

我希望使用CompletableFuture进行一些推荐。

如果我有一个整数列表,对于每个整数,我想执行3个动作,这需要一些时间。例如,相乘,相除和相减。

对于结果,它应该是map,其中key是整数,值是具有三个操作结果的列表。

方案1:如果我要在处理完一个整数后将结果写入映射,那么下面是执行此操作的好方法吗?

for (int x : nums) {
  CompletableFuture<Integer> multiply = CompletableFuture.supplyAsync(() -> multiply(x));
  CompletableFuture<Integer> divide = CompletableFuture.supplyAsync(() -> divide(x));
  CompletableFuture<Integer> subtract = CompletableFuture.supplyAsync(() -> subtract(x));

  CompletableFuture<Void> allRequests = CompletableFuture.allOf(multiple, divide, substract);

  //iterate the three CompletableFuture and add to the map.
}

方案2:如果我想将结果写到地图上,直到完成所有过程。

List<CompletableFuture<Void>> allRequests = new ArrayList<>();

for (int x : nums) {
  CompletableFuture<Integer> multiply = CompletableFuture.supplyAsync(() -> multiply(x));
  CompletableFuture<Integer> divide = CompletableFuture.supplyAsync(() -> divide(x));
  CompletableFuture<Integer> subtract = CompletableFuture.supplyAsync(() -> subtract(x));

  CompletableFuture<Void> allRequestsPerNum = CompletableFuture.allOf(multiple, divide, substract);

  allRequests.add(allRequestsPerNum);
}

CompletableFuture.allOf(allRequest);

//How am I suppose to build the result?

对于场景2,看起来如果我们在for循环内调用CompletableFuture.allOf,这意味着在移至下一个数字之前需要完成三个操作?

java multithreading completable-future
2个回答
0
投票

您可以使用CompletableFuture中内置的功能,未经测试,因此可能存在一些小问题。它应该给您一个不错的主意。

    List<CompletableFuture<Void>> allRequests = new ArrayList<>();

    for (int x : nums) {
         allRequests.add(CompletableFuture.allOf(
                CompletableFuture.supplyAsync(() -> multiply(x)).thenApplyAsync(() -> addToMap()),
                CompletableFuture.supplyAsync(() -> divide(x)).thenApplyAsync(() -> addToMap()),
                CompletableFuture.supplyAsync(() -> subtract(x)).thenApplyAsync(() -> addToMap())));
    }
    CompletableFuture.allOf(allRequests.toArray(new CompletableFuture[])).join();

0
投票

类似以下内容应该适合您:

如评论中所述,我不保证通过这种方式进行操作会带来任何性能上的好处。我也没有保证这是这样做的“最佳实践”。

// Keep all the futures around
final Collection<CompletableFuture<?>> futures = new ArrayList<>();

// And prepare the resulting map
final Map<Integer, List<Integer>> map = new HashMap<>();

for (int x : Arrays.asList(1, 2, 3)) {
    // Create the map value List.
    // Initialise it with some default values so that 'set'
    // works.  Use a concurrent-safe List so that there's
    // no risk of corruption from the async operations.
    final List<Integer> value = new CopyOnWriteArrayList<>(Arrays.asList(0, 0, 0));

    // Put the key and List (not yet ready) into the Map
    map.put(x, value);

    // Add all of your futures to your tracking Collection.
    // Note: each future now includes setting the appropriate
    // entry in the List to that result.
    futures.add(CompletableFuture.supplyAsync(() -> 2 * x)
            .thenAcceptAsync(result -> value.set(0, result)));
    futures.add(CompletableFuture.supplyAsync(() -> 2 / x)
            .thenAcceptAsync(result -> value.set(1, result)));
    futures.add(CompletableFuture.supplyAsync(() -> 2 - x)
            .thenAcceptAsync(result -> value.set(2, result)));
}

// Wait for them all to complete.
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
© www.soinside.com 2019 - 2024. All rights reserved.