目次
1、CompletableFuture是什么?
2、CompletableFuture和Future、CompletionStage的关系?
3、CompletableFuture常用方法
3.1、 创建 CompletableFuture 实例
3.2、完成时触发thenApply、thenAccept、thenRun
3.3、组合多个 CompletableFuture
3.4、非常处理处罚
3.5、其他方法
4、利用CompletableFuture 实现做肉丝面小案例
1、CompletableFuture是什么?
CompletableFuture是Java 8中引入的一个异步编程工具类,用于举行非壅闭的异步编程。它是Future接口的扩展,提供了更机动、更强大的功能。
CompletableFuture可以用于处理处罚异步操纵,比方网络哀求、数据库查询等。与传统的线程和回调方法相比,CompletableFuture提供了更轻便和方便的编程模子。
利用CompletableFuture的重要步调如下:
- 创建一个CompletableFuture对象,可以通过CompletableFuture类的静态方法来创建,如CompletableFuture.supplyAsync()和CompletableFuture.runAsync()。
- 调用CompletableFuture对象的方法来界说异步操纵的实验逻辑。可以利用thenApply()、thenAccept()和thenRun()等方法来对结果举行处理处罚,大概利用whenComplete()和handle()等方法来处理处罚非常环境。
- 利用CompletableFuture对象的get()方法来获取异步操纵的结果,大概利用join()方法来等候异步操纵的完成。
CompletableFuture还提供了一些其他功能,如组合多个CompletableFuture对象、并行实验异步任务、处理处罚超时等。通过这些功能,可以更机动地处理处罚复杂的异步编程需求。
总之,CompletableFuture是一个功能强大的异步编程工具类,提供了轻便、方便和机动的编程模子,可以资助开辟者更好地处理处罚异步操纵。
2、CompletableFuture和Future、CompletionStage的关系?
CompletableFuture 是 Future 接口的一个实现类,而且也实现了 CompletionStage 接口。
Future 接口代表一个异步盘算的结果,可以通过 get() 方法来获取盘算结果。但是 Future 接口中的方法较为有限,只能判定盘算是否完成、取消盘算和获取盘算结果(壅闭等候大概超时等候)等操纵。
CompletableFuture 类提供了更多的操纵方法,可以更方便地处理处罚异步盘算的结果。我们可以对盘算结果实验一系列的操纵,好比转换、组合、非常处理处罚等。它还提供了一些便捷的静态方法,可以将同步方法转换为异步方法,而且可以指定线程池大概实验器来实验异步操纵。
CompletionStage 接口是 CompletableFuture 的父接口,它界说了一些组合操纵的方法,而且可以与 CompletableFuture 举行链式调用。CompletableFuture 实现了 CompletionStage 接口,以是 可以利用 CompletionStage 接口中的方法。
综上所述,可以得出一下结论:
(1)CompletableFuture 是对 Future 的增强,而且也是 CompletionStage 的实现类。
(2)CompletableFuture 提供了更多的操纵方法和扩展功能,可以更机动地处理处罚异步盘算的结果。
(3)CompletionStage 接口则提供了一些组合操纵的方法,可以方便地对异步盘算结果举行串行或并行处理处罚。
3、CompletableFuture常用方法
3.1、 创建 CompletableFuture 实例
- static CompletableFuture<Void> completedFuture(U value)
- static CompletableFuture<Void> runAsync(Runnable runnable)
- static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
- static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
- static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
复制代码 (1)CompletableFuture.completedFuture
方法用来创建一个已经完成的CompletableFuture对象。这个对象的结果是事先指定好的一个值大概非常。
这个方法有一个参数,可以是恣意的范例,表现这个CompletableFuture对象的结果。返回值是一个已经完成的CompletableFuture对象。
- CompletableFuture<Void> completedFuture = CompletableFuture.completedFuture(null);
复制代码 (2)runAsync
方法吸收一个Runnable参数,表现实验无返回值的异步任务。它返回一个CompletableFuture<Void>对象。
- CompletableFuture<Void> runAsyncFuture = CompletableFuture.runAsync(() -> System.out.println("Run async"));
复制代码 (3)supplyAsync
方法吸收一个Supplier<T>参数,表现实验有返回值的异步任务。它返回一个CompletableFuture<T>对象。
- CompletableFuture<String> supplyAsyncFuture = CompletableFuture.supplyAsync(() -> "Supply async");
复制代码 runAsync和supplyAsync都是CompletableFuture类的静态方法,用于实验异步任务。
区别在于方法的参数和返回值范例差异。runAsync实验无返回值的异步任务,supplyAsync实验有返回值的异步任务,并将结果包装在CompletableFuture对象中返回。
3.2、完成时触发thenApply、thenAccept、thenRun
- <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)
- <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)
- CompletableFuture<Void> thenAccept(Consumer<? super T> action)
- CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action)
- CompletableFuture<Void> thenRun(Runnable action)
- CompletableFuture<Void> thenRunAsync(Runnable action)
复制代码 (1)thenApply(Function<? super T,? extends U> fn)
这个方法在 CompletableFuture 完成后,将利用该 CompletableFuture 的结果作为输入,实验给定的 Function。这个 Function 担当一个范例为 T 的参数并返回一个范例为 U 的结果。返回一个新的 CompletableFuture<U>,它将在 Function 实验完毕后完成。
- CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello").thenApply(s -> s + " World");
- System.out.println(future.get()); //Hello World
复制代码 (2)thenApplyAsync(Function<? super T,? extends U> fn)
与 thenApply 类似,但 thenApplyAsync 会异步地实验给定的 Function。这意味着它将在一个新线程中实验 Function,而不是在完成原始 CompletableFuture 的同一个线程中。
(3)thenAccept(Consumer<? super T> action)
这个方法在 CompletableFuture 完成后,将利用该 CompletableFuture 的结果作为输入,实验给定的 Consumer。Consumer 担当一个范例为 T 的参数并实验一些操纵,但不会返回任何结果。返回一个新的 CompletableFuture<Void>。
- CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");
- CompletableFuture<Void> stringCompletableFuture = future.thenAccept(s -> System.out.println(s+" World"));//Hello World
复制代码 (4)thenAcceptAsync(Consumer<? super T> action)
与 thenAccept 类似,但 thenAcceptAsync 会异步地实验给定的 Function。这意味着它将在一个新线程中实验 Function。
(5)thenRun(Runnable action)
这个方法在 CompletableFuture 完成后实验给定的 Runnable。这个 Runnable 不担当任何参数,也不返回任何结果。返回一个新的 CompletableFuture<Void>。
- CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");
- CompletableFuture<Void> futureRun = future.thenRun(() -> System.out.println("Action completed"));
复制代码 (6)thenRunAsync(Runnable action)
与 thenRun 类似,但 thenRunAsync 会异步地实验给定的 Runnable。这意味着它将在一个新线程中实验 Runnable。
区别:
- thenApply 与 thenApplyAsync 的区别在于实验 Function 的线程。thenApply 通常在完成原始 CompletableFuture 的同一个线程中实验,而 thenApplyAsync 总是在一个新线程中实验。
- thenAccept 与 thenAcceptAsync,以及 thenRun 与 thenRunAsync 的区别同理。
- thenApply、thenAccept 和 thenRun 是同步操纵,意味着它们在当火线程上实验,除非前一个阶段是异步完成的。
- thenApplyAsync、thenAcceptAsync 和 thenRunAsync 是异步操纵,意味着它们会在差异的线程上实验,通常是 ForkJoinPool.commonPool() 中的线程,大概可以通过提供一个自界说的 Executor 来指定。
3.3、组合多个 CompletableFuture
- static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
- static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
复制代码 (1)allOf(CompletableFuture<?>... cfs)
该方法吸收一个 CompletableFuture 数组,并返回一个新的 CompletableFuture<Void> 对象。这个方法会等候全部的 CompletableFuture 对象都实验完成,然后返回一个新的 CompletableFuture,它会在全部的 CompletableFuture 对象都实验完成后完成。如果恣意一个 CompletableFuture 对象抛出非常,那么它会将非常通报给返回的 CompletableFuture 对象。
比方,假设有两个 CompletableFuture 对象 cf1 和 cf2,我们可以利用 allOf 方法等候它们都实验完成:
- CompletableFuture<Void> allFutures = CompletableFuture.allOf(cf1, cf2);
复制代码 (2)anyOf(CompletableFuture<?>... cfs)
该方法与 allOf 方法类似,但是它会等候恣意一个 CompletableFuture 对象实验完成,然后返回一个新的 CompletableFuture<Object> 对象。假云云中恣意一个 CompletableFuture 对象完成时有返回值,那么它将利用第一个完成的 CompletableFuture 的返回值作为返回值通报给返回的 CompletableFuture 对象。
- CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(cf1, cf2);
复制代码 总结:
这两个方法都黑白壅闭的,即它们会立刻返回一个 CompletableFuture 对象,不会等候 CompletableFuture 对象的实验完成。可以利用 thenApply、thenAccept 大概 thenRun 等方法来注册回调函数,以处理处罚 CompletableFuture 的结果。
3.4、非常处理处罚
- <U> CompletableFuture<U> exceptionally(Function<Throwable, ? extends U> fn)
- <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn)
复制代码 (1)CompletableFuture<U> exceptionally(Function<Throwable, ? extends U> fn)
该方法可以用来处理处罚非常环境。它担当一个Function参数,该参数是一个非常处理处罚函数,用于处理处罚出现的非常。如果CompletableFuture中发生了非常,那么这个非常会被通报给exceptionally方法,并由该方法的参数函数举行处理处罚。处理处罚完成后,exceptionally方法会返回一个新的CompletableFuture对象,该对象的结果是由非常处理处罚函数的返回值决定。如果原始的CompletableFuture没有发生非常(即正常完成),那么exceptionally方法会返回一个与原始CompletableFuture雷同的CompletableFuture对象。
(2)CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn)
该方法也可以用于处理处罚非常环境。它担当一个BiFunction参数,该参数是一个处理处罚函数,用于处理处罚正常结果或非常。如果CompletableFuture正常完成,那么handle方法会将结果和非常值作为参数通报给处理处罚函数。处理处罚函数的返回值将被用作新的CompletableFuture的结果。如果CompletableFuture发生非常,那么handle方法会将非常和null作为参数通报给处理处罚函数。处理处罚函数的返回值也将被用作新的CompletableFuture的结果。
- public class CompletableFutureDemo {
- public static void main(String[] args) {
- // 创建CompletableFuture
- CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
- // 模拟抛出异常
- throw new RuntimeException("Exception occurred");
- });
- // 使用exceptionally处理异常
- CompletableFuture<String> exceptionHandledFuture = future.exceptionally(ex -> {
- return "Exception handled: " + ex.getMessage();
- });
- // 使用handle处理结果或异常
- CompletableFuture<String> resultFuture = future.handle((res, ex) -> {
- if (ex != null) {
- return "Exception handled: " + ex.getMessage();
- } else {
- return res;
- }
- });
- // 打印结果
- System.out.println(exceptionHandledFuture.join());
- System.out.println(resultFuture.join());
- }
- }
复制代码 总结起来,exceptionally方法和handle方法都是用于处理处罚CompletableFuture发生的非常环境。它们提供了一种方式来处理处罚非常并返回一个新的CompletableFuture对象,使得我们可以大概在异步操纵完成后举行进一步的处理处罚。
3.5、其他方法
- <U> CompletableFuture<U> newIncompleteFuture()
- boolean complete(T value)
- boolean completeExceptionally(Throwable ex)
- T getNow(T valueIfAbsent)
- T join()
- boolean isDone()
- boolean isCancelled()
- boolean cancel(boolean mayInterruptIfRunning)
复制代码 (1)<U> CompletableFuture<U> newIncompleteFuture()
这个方法返回一个新的 CompletableFuture,它与当前实例具有雷同的特性(比方,异步实验的特性),但是没有完成的值或非常。通常用于创建自界说的 CompletableFuture 实现或扩展。
- CompletableFuture<String> future = new CompletableFuture<>();
- CompletableFuture<String> newFuture = future.newIncompleteFuture();
复制代码 (2)boolean complete(T value)
这个方法实验将给定的值设置为 CompletableFuture 的结果。如果 CompletableFuture 已经完成,则返回 false;否则,它会被设置为给定的值,并返回 true。
- CompletableFuture<String> future = new CompletableFuture<>();
- boolean completed = future.complete("Completed value");
- System.out.println("Future completed: " + completed); // 输出 true
复制代码 (3)boolean completeExceptionally(Throwable ex)
这个方法实验将给定的非常设置为 CompletableFuture 的非常结果。如果 CompletableFuture 已经完成,则返回 false;否则,它会被设置为给定的非常,并返回 true。
- CompletableFuture<String> future = new CompletableFuture<>();
- boolean completedExceptionally = future.completeExceptionally(new Exception("Error"));
- System.out.println("Future completed exceptionally: " + completedExceptionally); // 输出 true
复制代码 (4)T getNow(T valueIfAbsent)
这个方法返回 CompletableFuture 的当前值,如果没有完成,则返回给定的默认值 valueIfAbsent。
- CompletableFuture<String> future = CompletableFuture.completedFuture("Hello");
- String value = future.getNow("Default");
- System.out.println(value); // 输出 Hello
- CompletableFuture<String> futureNotCompleted = new CompletableFuture<>();
- String defaultValue = futureNotCompleted.getNow("Default");
- System.out.println(defaultValue); // 输出 Default
复制代码 (5)T join()
这个方法与 getNow 类似,但它会壅闭当火线程直到 CompletableFuture 完成,然后返回结果。如果 CompletableFuture 已经完成,它将立刻返回结果。
- CompletableFuture<String> future = CompletableFuture.completedFuture("Hello");
- String value = future.join();
- System.out.println(value); // 输出 Hello
复制代码 (6)boolean isDone()
这个方法返回 CompletableFuture 是否已经完成。完成大概是正常完成,也大概是由于非常。
- CompletableFuture<String> future = new CompletableFuture<>();
- System.out.println("Future is done: " + future.isDone()); // 输出 false
- future.complete("Completed");
- System.out.println("Future is done: " + future.isDone()); // 输出 true
复制代码 (7)boolean isCancelled()
这个方法返回 CompletableFuture 是否已经被取消。
- CompletableFuture<String> future = new CompletableFuture<>();
- System.out.println("Future is cancelled: " + future.isCancelled()); // 输出 false
- boolean cancelled = future.cancel(true);
- System.out.println("Future is cancelled: " + future.isCancelled()); // 输出 true
复制代码 (8)boolean cancel(boolean mayInterruptIfRunning)
这个方法实验取消 CompletableFuture 的实验。如果 CompletableFuture 已经完成,则返回 false。如果 mayInterruptIfRunning 为 true,而且 CompletableFuture 正在运行,那么它将被停止。
- CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- return "Result";
- });
- boolean cancelled = future.cancel(true);
- System.out.println("Future cancelled: " + cancelled); // 输出 true
复制代码 4、利用CompletableFuture 实现做肉丝面小案例
如今为了好明确并发编程的头脑,这里我准备了一个贴合现实的小案例,就是做一碗肉丝面,我们先梳理一下做面的步调过程,大抵是一下几个步调
1、备菜(切肉丝、切葱姜蒜、调味料、洗青菜、面条) (5分钟)
2、炒菜(下入肉丝、葱姜蒜翻炒、调味料调味) (2分钟)
3、煮开水 (10分钟)
4、下面条(煮3分钟)
5、下青菜再煮一会(1分钟)
6、完成
如果按照同步实验的话,就是代码依次从上往下实验,统共必要21分钟的时间,那么我们通过并发头脑来节省一下时间。我们思索一下,备菜和煮开水是不是可以一起实验,由于我可以两个一起实验,如许是不是就可以节省时间了。具体实现参考下面代码
- import java.util.concurrent.*;
- public class CompletableFutureDemo {
- public static void main(String[] args) {
- // 创建自定义线程池
- int corePoolSize = 2; // 核心线程数
- int maximumPoolSize = 4; // 最大线程数
- long keepAliveTime = 60; // 非核心线程空闲存活时间
- TimeUnit unit = TimeUnit.SECONDS; // 时间单位
- BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(); // 阻塞队列
- ThreadFactory threadFactory = Executors.defaultThreadFactory(); // 线程工厂
- RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy(); // 拒绝策略
- ThreadPoolExecutor customThreadPool = new ThreadPoolExecutor(
- corePoolSize,
- maximumPoolSize,
- keepAliveTime,
- unit,
- workQueue,
- threadFactory,
- handler
- );
- // 步骤1:备菜
- long startTime = System.currentTimeMillis();
- CompletableFuture<Void> prepareIngredients = CompletableFuture.runAsync(() -> {
- System.out.println("开始备菜...");
- // 模拟切肉丝、切葱姜蒜、准备调味料、洗青菜、面条
- try {
- TimeUnit.SECONDS.sleep(5);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("备菜完成。");
- },customThreadPool);
- // 步骤2:炒菜 使用thenRunAsync,等待步骤1执行结束再执行炒菜步骤
- CompletableFuture<Void> stirFry = prepareIngredients.thenRunAsync(() -> {
- System.out.println("开始炒菜...");
- // 模拟下入肉丝、葱姜蒜翻炒、调味料调味
- try {
- TimeUnit.SECONDS.sleep(2);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("炒菜完成。");
- },customThreadPool);
- // 步骤3:煮开水 可以直接使用runAsync,与步骤1备菜并行执行
- CompletableFuture<Void> boilWater = CompletableFuture.runAsync(() -> {
- System.out.println("开始煮开水...");
- // 模拟煮开水的过程
- try {
- TimeUnit.SECONDS.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("水开了。");
- },customThreadPool);
- // 步骤4:下面条 使用allOf 等待步骤2、步骤3执行结束再执行
- CompletableFuture<Void> cookNoodles = CompletableFuture.allOf(stirFry, boilWater).thenRunAsync(() -> {
- System.out.println("下面条...");
- // 模拟煮面条的过程
- try {
- TimeUnit.SECONDS.sleep(3);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("面条煮熟了。");
- },customThreadPool);
- // 步骤5:下青菜再煮 等待步骤4结束执行
- CompletableFuture<Void> cookVegetables = cookNoodles.thenRunAsync(() -> {
- System.out.println("下青菜...");
- // 模拟下青菜的过程
- try {
- TimeUnit.SECONDS.sleep(1);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("青菜煮熟了。");
- System.out.println("完成烹饪,可以享用了!");
- },customThreadPool);
- // 等待所有步骤完成
- try {
- cookVegetables.get();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- } catch (ExecutionException e) {
- throw new RuntimeException(e);
- }finally {
- // 关闭线程池
- customThreadPool.shutdown();
- }
- long endTime = System.currentTimeMillis();
- System.out.println("共消耗了:" + (endTime - startTime) / 1000 + "秒");
- }
- }
复制代码
可以看到,通过异步实验,14分钟(贴合现实,换算为分钟)就完成了肉丝面的制作,节省了7分钟的时间,服从提升了33%。
感谢您的阅读,制作不易,喜欢这篇文章的小同伴们点赞关注支持一下吧。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金 |