Предположим, что у вас есть метод, который является "псевдо-асинхронным", как вы описываете, то есть он имеет асинхронный API, но требует некоторой блокировки для выполнения:
private final static Object lock = new Object();
private static CompletableFuture<Boolean> pseudoAsyncCall(int input) {
return CompletableFuture.supplyAsync(() -> {
synchronized (lock) {
System.out.println("Executing for " + input);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return input > 3;
}
});
}
и List<Integer>
входов, которыевы хотите проверить этот метод, вы можете проверить каждый из них в последовательности с рекурсивной композицией:
public static CompletableFuture<Integer> findMatch(List<Integer> inputs) {
return findMatch(inputs, 0);
}
private static CompletableFuture<Integer> findMatch(List<Integer> inputs, int startIndex) {
if (startIndex >= inputs.size()) {
// no match found -- an exception could be thrown here if preferred
return CompletableFuture.completedFuture(null);
}
return pseudoAsyncCall(inputs.get(startIndex))
.thenCompose(result -> {
if (result) {
return CompletableFuture.completedFuture(inputs.get(startIndex));
} else {
return findMatch(inputs, startIndex + 1);
}
});
}
Это будет использоваться так:
public static void main(String[] args) {
List<Integer> inputs = Arrays.asList(0, 1, 2, 3, 4, 5);
CompletableFuture<Integer> matching = findMatch(inputs);
System.out.println("Found match: " + matching.join());
}
Вывод:
Executing for 0
Executing for 1
Executing for 2
Executing for 3
Executing for 4
Found match: 4
Как видите, он не вызывается для ввода 5
, в то время как ваш API (findMatch()
) остается асинхронным.