我在java 8中使用Completable future我想编写一个方法,根据接收到的参数,并行运行带有副作用的多个任务然后返回它们的"组合"未来(使用CompletableFuture.allOf()),或者什么都不做并返回一个已经完成的未来.
但是,allOf返回一个CompletableFuture<Void>:
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
Run Code Online (Sandbox Code Playgroud)
并且创建已经完成的未来的唯一方法就是使用completedFuture(),它需要一个值:
public static <U> CompletableFuture<U> completedFuture(U value)
Run Code Online (Sandbox Code Playgroud)
返回已使用给定值完成的新CompletableFuture.
并且Void是不可实现的,所以我需要另一种方法来创建已经完成的类型未来CompletableFuture<Void>.
做这个的最好方式是什么?
将代码直接传递给线程vs使用CompletableFuture的优势是什么?
Thread thread = new Thread(() -> {do something});
thread.start();
Run Code Online (Sandbox Code Playgroud)
VS
CompletableFuture<Void> cf1 =
CompletableFuture.runAsync(() -> {do something});
Run Code Online (Sandbox Code Playgroud) 我正在尝试JDK 11中的新HTTP客户端API,特别是它执行请求的异步方式.但有些事情我不确定我理解(有点像实现方面).在文档中,它说:
在可行的
CompletableFuture情况下,返回实例的异步任务和相关操作将在客户端提供的线程上执行Executor.
据我所知,这意味着如果我在创建HttpClient对象时设置自定义执行程序:
ExecutorService executor = Executors.newFixedThreadPool(3);
HttpClient httpClient = HttpClient.newBuilder()
.executor(executor) // custom executor
.build();
Run Code Online (Sandbox Code Playgroud)
然后,如果我异步发送请求并在返回时添加依赖操作CompletableFuture,则依赖操作应在指定的执行程序上执行.
httpClient.sendAsync(request, BodyHandlers.ofString())
.thenAccept(response -> {
System.out.println("Thread is: " + Thread.currentThread().getName());
// do something when the response is received
});
Run Code Online (Sandbox Code Playgroud)
但是,在上面的依赖操作(使用者中thenAccept)中,我看到执行它的线程来自公共池而不是自定义执行器,因为它打印Thread is: ForkJoinPool.commonPool-worker-5.
这是实施中的错误吗?或者我错过了什么?我注意到它说"实例是在客户端的执行程序提供的线程上执行的,在实际可行的情况下",这是不适用的情况?
请注意,我也尝试了thenAcceptAsync,结果相同.
我有一个HttpClient具有返回功能的类CompletableFuture:
public class HttpClient {
public static CompletableFuture<int> getSize() {
CompletableFuture<int> future = ClientHelper.getResults()
.thenApply((searchResults) -> {
return searchResults.size();
});
return future;
}
}
Run Code Online (Sandbox Code Playgroud)
然后另一个函数调用此函数:
public class Caller {
public static void caller() throws Exception {
// some other code than can throw an exception
HttpClient.getSize()
.thenApply((count) -> {
System.out.println(count);
return count;
})
.exceptionally(ex -> {
System.out.println("Whoops! Something happened....");
});
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我想写一个测试来模拟ClientHelper.getResults 失败,所以我写了这个:
@Test
public void myTest() {
HttpClient mockClient = mock(HttpClient.class);
try …Run Code Online (Sandbox Code Playgroud) CompletableFuture.completedFuture()返回CompletedFuture已使用给定值完成的.
我们如何构建一个CompletableFuture已经完成的异常?
意思是,我希望将来抛出一个异常,而不是返回一个值.
有没有办法在 Java 中安排 CompletableFuture?我想要做的是安排一个要延迟执行的任务,并在它完成时将它与其他要异步执行的操作链接起来。到目前为止,我没有找到任何方法来做到这一点。
对于好的 ol' Futures,我们有例如 ScheduledExecutorService,我们可以在其中安排一个任务以延迟执行,如下所示:
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
Future<String> future = scheduledExecutorService.schedule(() -> "someValue", 10, TimeUnit.SECONDS);
Run Code Online (Sandbox Code Playgroud)
CompletableFutures 有没有类似的方法?
我想要实现的是,通过以这种简单的方式使用多线程,在我的 RESTApi 控制器中使用 @Async 和 CompletableFuture 可以获得更好的性能吗?
这是我所做的,这是我的控制器:
@PostMapping("/store")
@Async
public CompletableFuture<ResponseEntity<ResponseRequest<CategoryBpsjResponseDto>>> saveNewCategoryBPSJ(@Valid @RequestBody InputRequest<CategoryBPSJRequestDto> request) {
CompletableFuture<ResponseEntity<ResponseRequest<CategoryBpsjResponseDto>>> future = new CompletableFuture<>();
future.complete(ResponseEntity.ok(new ResponseRequest<>("Okay", categoryBPSJService.save(request))));
return future;
}
Run Code Online (Sandbox Code Playgroud)
VS
@PostMapping("/store")
public ResponseEntity<ResponseRequest<CategoryBpsjResponseDto>> saveNewCategoryBPSJ(@Valid @RequestBody InputRequest<CategoryBPSJRequestDto> request) {
return ResponseEntity.ok(new ResponseRequest<>("okay", categoryBPSJService.save(request));
}
Run Code Online (Sandbox Code Playgroud)
正如你在我的第一个控制器函数中看到的,我在我的函数响应中添加了 CompletableFuture,但是在我的服务中,我在这一行中保存的categoryBPSJService.save(request)不是异步的,只是一个看起来像这样的简单函数:
public CategoryBpsjResponseDto save(InputRequest<CategoryBPSJRequestDto> request) {
CategoryBPSJRequestDto categoryBPSJDto = request.getObject();
Boolean result = categoryBPSJRepository.existsCategoryBPSJBycategoryBPSJName(categoryBPSJDto.getCategoryBPSJName());
if(result){
throw new ResourceAlreadyExistException("Category BPSJ "+ categoryBPSJDto.getCategoryBPSJName() + " already exists!");
}
CategoryBPSJ categoryBPSJ = new CategoryBPSJ();
categoryBPSJ = map.DTOEntity(categoryBPSJDto);
categoryBPSJ.setId(0L); …Run Code Online (Sandbox Code Playgroud) 在Java 8中,接口或抽象类更好地定义API返回CompletableFuture而不是返回Future?考虑到它是丑陋转化Future到CompletableFuture和事实CompletableFuture将会给调用者直接使用功能的风格更加灵活,这可能是一个API只返回一个很好的理由Future?
假设我有一个CompletableFuture,它包含一个阻塞调用,比如使用JDBC查询后端.在这种情况下,由于我没有将任何执行程序服务作为参数传递给CompletableFuture.supplyAsync(),因此通过后端获取资源的实际阻塞工作应该由公共Fork/Join池中的线程完成.让来自普通FJpool的线程阻塞调用不是不好的做法吗?我在这里的优点是我的主线程没有阻塞,因为我委托阻塞调用异步运行.在这里检查abt JDBC调用是否阻塞.如果这个推论是正确的,为什么可以选择使用带有CompletableFuture的默认公共FJpool?
CompletableFuture<List<String>> fetchUnicorns =
CompletableFuture.supplyAsync(() -> {
return unicornService.getUnicorns();
});
fetchUnicorns.thenAccept(/**Do something with the result*/);
Run Code Online (Sandbox Code Playgroud) Coroutine async返回Deferred<T>,有懒惰执行和等待用法的例子.
但是,我们如何等待任何一个Deffered实例完成?
简而言之
// whats the equivalent of CompletableFuture.anyOf(...)?
// is this how we do it? if so how costly is this?
select<Unit> {
deffered1.onAwait {}
deffered2.onAwait {}
}
Run Code Online (Sandbox Code Playgroud) java ×9
java-8 ×4
asynchronous ×3
concurrency ×2
coroutine ×1
exception ×1
future ×1
http ×1
interface ×1
java-11 ×1
kotlin ×1
mockito ×1
performance ×1
spring ×1