JDK17 CompletableFuture 一 调用

背景

Java的异步并发Future接口表示异步计算的结果。CompletableFuture是对Future接口的增强,它实现CompletionStage接口,允许链式组合异步操作,组合多个异步任务的结果,处理异常情况,任务结束时执行回调方法。

CompletableFuture定义与用法

public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
   
    volatile Object result;       // Either the result or boxed AltResult
    volatile Completion stack;
}

CompletableFuture类有2个成员变量,volatile修饰符保证多线程环境下变量可见性。result表示当前任务的结果,可能是正常结果,可能是异常对象。stack是当前任务确定结果后接下来所有执行的任务栈。

CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)

常用的创建方法中,supplyAsync有返回值,runAsync没有返回值(返回值类型为Void)。async表示异步,即runnable任务不由调用线程执行,而是由线程池执行。
默认线程池是ForkJoinPool,这是一个全局唯一的线程池。为了管理任务,建议对不同类型任务分别分配线程池。

Completion

abstract static class Completion extends ForkJoinTask<Void>
        implements Runnable, AsynchronousCompletionTask {
   
	volatile Completion next;
	abstract CompletableFuture<?> tryFire(int mode);
	abstract boolean isLive();
    public final void run()                {
    tryFire(ASYNC); }
    public final boolean exec()            {
    tryFire(ASYNC); return false; }
    public final Void getRawResult()       {
    return null; }
    public final void setRawResult(Void v) {
   }
}

CompletionCompletableFuture的内部类。CompletableFuture强调存储任务结果,而Completion强调计算单个任务以及组合多个任务,强调动作,所以它继承Runnable,可以异步执行。例子:

ExecutorService executor = new ThreadPoolExecutor(5, 5, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5));
CompletableFuture base = new CompletableFuture();
base.thenApply(u -> {
   
    return "h";
});
base.thenAcceptAsync(s -> System.out.println(s), executor);
base.thenRunAsync(() -> System.out.println("c"), executor);
// 时间点1
base.complete("s");

程序运行到时间点1,base任务还没完成(等base.complete("s")结束base对象的result=s才算完成),它将三个thenXxx()方法装在栈里,以便将来调用,关系如图。每个thenXxx()方法都对应一个Completition对象,后调用的方法在栈顶,先调用的在栈底。栈的底层是链表。stack表示当前任务完成后将要执行的任务,即栈顶元素。
注意:这里的栈是Treiber stacks,用CAS原子性更改栈顶元素,实现线程安全地更改栈。
在这里插入图片描述
源码中thenApply()方法对应的不是Completion类本身,而是它的子类UniApply类。Completion的子类很多,如下图,它们的区别是

  1. 输入不同。比如Uni开头的子类表示1个输入,Bi开头的子类表示2个输入。比如UniApply接收Function类型任务,UniRun接受Runnable类型任务。
  2. 功能不同。比如BiRun表示两个输入都已运算结束才行,OrRun表示其中1个结束就行。比如Signaller类用于当前线程挂起后(比如get()方法)将来唤醒本线程(就是执行LockSupport.unpark(本线程对象))。
    在这里插入图片描述
    图片来自https://tech.meituan.com/2022/05/12/principles-and-practices-of-completablefuture.html。

thenApplyAsync方法

CompletableFuture#thenApplyAsync()为例,分析执行流程。如果前置任务已经有结果,那么不加入stack栈,直接运算,如果前置任务还没算完,那么用unipush()方法加入栈。

public <
### JDK 17 HttpClient 使用指南和特性介绍 #### HttpClient 类概述 `HttpClient` 是 JavaJDK 9 开始引入的个新的 HTTP 客户端 API,在后续版本中不断得到增强和完善。到了 JDK 17,这个类已经非常成熟稳定,并且成为标准库的部分。 #### 创建 HttpClient 实例 可以通过静态工厂方法 `HttpClient.newHttpClient()` 来创建个新的 `HttpClient` 对象实例[^1]: ```java import java.net.http.HttpClient; // 创建默认配置的 HttpClient 实例 HttpClient client = HttpClient.newHttpClient(); ``` #### 发送同步 GET 请求 对于简单的同步请求来说,可以构建个 `HttpRequest` 并调用 `send()` 方法来执行它。这里展示如何发起次基本的 GET 请求并获取响应体作为字符串形式的数据[^3]: ```java import java.net.URI; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class Example { public static void main(String[] args) throws Exception { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("http://example.com")) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` #### 处理异步 POST 请求 当需要处理更复杂的场景比如提交表单数据时,则可以选择使用异步方式发送 POST 请求。下面的例子展示了怎样设置请求头以及传递 JSON 数据给服务器: ```java import java.net.http.HttpHeaders; import java.nio.file.Path; import java.util.concurrent.CompletableFuture; public class AsyncExample { private final HttpClient httpClient = HttpClient.newHttpClient(); CompletableFuture<Void> postJsonAsync(Path jsonFilePath){ var requestBody = Files.readString(jsonFilePath); HttpRequest request = HttpRequest.newBuilder() .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(requestBody)) .uri(new URI("https://jsonplaceholder.typicode.com/posts")) .build(); return httpClient.sendAsync(request, BodyHandler.asString()) .thenApply(HttpResponse::body) .thenAccept(System.out::println); } } ``` #### 支持 HTTPS 协议和其他高级功能 除了上述基础操作外,`HttpClient` 还支持 SSL/TLS 加密连接(即 HTTPS),能够自动重定向、管理 cookies 等更多实用的功能。开发者可以根据实际需求灵活调整客户端的行为模式以满足不同的应用场景要求[^2].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值