我需要创建一个通用的CompletableFuture对象数组,以便我可以将它传递给CompletableFuture.allOf方法CompletableFuture来同步线程。但由于它是通用的,我无法创建它。一个明显的解决方案是创建一个 List 然后调用toArray它,但效率很低。有没有更好的方法?这是我的代码:
// Current solution:
List<CompletableFuture<List<ReportComparable>>> newReports = new ArrayList<>();
// Loop and add CompletableFuture objects to this list
// Collect all the retrieved objects here(Sync Threads).
try {
List<List<ReportComparable>> newReps = CompletableFuture.allOf((CompletableFuture<?>[]) newReports.toArray()).get();
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud) 考虑以下代码 -
public class TestCompletableFuture {
BiConsumer<Integer, Throwable> biConsumer = (x,y) -> {
System.out.println(x);
System.out.println(y);
};
public static void main(String args[]) {
TestCompletableFuture testF = new TestCompletableFuture();
testF.start();
}
public void start() {
Supplier<Integer> numberSupplier = new Supplier<Integer>() {
@Override
public Integer get() {
return SupplyNumbers.sendNumbers();
}
};
CompletableFuture<Integer> testFuture = CompletableFuture.supplyAsync(numberSupplier).whenComplete(biConsumer);
}
}
class SupplyNumbers {
public static Integer sendNumbers(){
return 25; // just for working sake its not correct.
}
}
Run Code Online (Sandbox Code Playgroud)
以上的事情很好.但是sendNumbers也可以在我的情况下抛出一个检查过的异常,例如:
class SupplyNumbers {
public …Run Code Online (Sandbox Code Playgroud) 问题:如何直接从 抛出自定义异常.exceptionally()?
List<CompletableFuture<Object>> futures =
tasks.stream()
.map(task -> CompletableFuture.supplyAsync(() -> businessLogic(task))
.exceptionally(ex -> {
if (ex instanceof BusinessException) return null;
//TODO how to throw a custom exception here??
throw new BadRequestException("at least one async task had an exception");
}))
.collect(Collectors.toList());
try {
List<Object> results = futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
} catch (CompletionException e) {
if (e.getCause() instanceof RuntimeException) {
throw (RuntimeException) e.getCause();
}
throw new RuntimeException(e.getCause());
}
Run Code Online (Sandbox Code Playgroud)
问题:我总是得到一个CompletionExceptionwho ex.getCause()is instanceof BadRequestException。
这可能吗?
我刚刚开始熟悉 Java 的 CompletableFuture 工具。我创建了一个小玩具应用程序来模拟几乎所有开发人员都会遇到的一些经常性用例。
在这个例子中,我只想将一个东西保存在数据库中,但在这样做之前我想检查该东西是否已经保存。
如果该事物已经在数据库中,则流程(可完成的未来链)应该停止并且不保存该事物。我正在做的是抛出一个异常,这样最终我就可以处理它并向服务的客户端提供一个好的消息,以便他知道发生了什么。
这是我到目前为止所尝试过的:
首先是尝试保存事物的代码,如果事物已在表中,则抛出错误:
repository
.query(thing.getId())
.thenCompose(
mayBeThing -> {
if (mayBeThing.isDefined()) throw new CompletionException(new ThingAlreadyExists());
else return repository.insert(new ThingDTO(thing.getId(), thing.getName()));
Run Code Online (Sandbox Code Playgroud)
这是我正在尝试运行的测试:
CompletableFuture<Integer> eventuallyMayBeThing =
service.save(thing).thenCompose(i -> service.save(thing));
try {
eventuallyMayBeThing.get();
} catch (CompletionException ce) {
System.out.println("Completion exception " + ce.getMessage());
try {
throw ce.getCause();
} catch (ThingAlreadyExist tae) {
assert (true);
} catch (Throwable t) {
throw new AssertionError(t);
}
}
Run Code Online (Sandbox Code Playgroud)
我从这个响应中采用了这种方式:从 CompletableFuture 抛出异常(投票最多的答案的第一部分)。
然而,这是行不通的。确实被抛出ThingAlreadyExist,但它从未被我的 try catch 块处理。我的意思是,这个:
catch (CompletionException …Run Code Online (Sandbox Code Playgroud) 假设我有这个示例代码并且在runAsync. 我的问题是这个异常是否会阻止在thenRun与thenRun此代码的调用方方法相同的线程中运行时被执行。
private void caller() {
CompletableFuture.runAsync(() -> {
try {
// some code
} catch (Exception e) {
throw new CustomException(errorMessage, e);
}
}, anInstanceOfTaskExecutor).thenRun(
// thenRun code
));
}
Run Code Online (Sandbox Code Playgroud)
我已经浏览了这个线程,它解释了如何处理从异步块抛出的异常(即通过阻塞和使用join)。我想知道thenRun如果CompletableFuture completesExceptionally.
更新:
我运行了一些代码来测试这个:
CompletableFuture.runAsync(() -> {
List<Integer> integerList = new ArrayList<>();
integerList.get(1); // throws exception
}).thenRun(() -> {
System.out.println("No exception occurred");
});
Run Code Online (Sandbox Code Playgroud)
它不打印任何内容,这意味着异常不会从异步块“传播到/到达”调用方方法的线程。我现在了解这里的预期行为,但我有以下问题:
我曾经有一个可调用的类
class SampleTask implements Callable<Double> {
@Override
public Double call() throws Exception {
return 0d;
}
}
Run Code Online (Sandbox Code Playgroud)
我曾经用来ExecutorService提交Callable.如何改用CompletableFuture.supplyAsync?
以下代码无法编译
SampleTask task = new SampleTask();
CompletableFuture.supplyAsync(task);
Run Code Online (Sandbox Code Playgroud)
不存在变量U类型的实例,因此SampleTask符合Supplier