CompletableFuture

本文详细介绍了Java中的CompletableFuture类,包括其基本用法如runAsync和supplyAsync,以及如何通过thenRun、thenAccept和thenApply来定义任务执行后的操作。此外还讲解了如何处理异常和使用自定义线程池。

之前的多线程处理

Runnable --> Void

Callable --> Future      (get() 阻塞等待结果,或者while一直等待结果)

现在的异步编程

等结果完成后,自动触发回调方法。

CompletableFunction

a) 提供要运行的任务

  • runAsync        无返回结果
  • supplyAsync   有返回结果

b)任务完成后触发

  • thenRun        完成任务时没有结果,然后接着运行下一个任务
  • thenAccept    完成任务时有结果,处理该结果不用返回数据。
  • thenApply      完成任务时有结果,处理改结果并返回新的数据。


c) 处理执行流程中碰到的异常

  • exceptionally  当异常情况发生时,处理异常信息。
  • handle            数据和异常同时由handle函数处理。

Testing Code:

package com.coupang.flink;

import org.junit.Test;

import java.time.LocalDateTime;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * description: TODO
 *
 * @author adore.chen
 * @date 2022-11-18
 */
public class CompletableFutureTest {

    @Test
    public void runAsync() {
        CompletableFuture<Void> completableFuture = CompletableFuture
                .runAsync(() -> {
                    System.out.println("First Runnable Task ... at " + LocalDateTime.now());
                    try {
                        TimeUnit.MILLISECONDS.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                })
                .thenRun(() -> System.out.println("Second Runnable Task ... at " + LocalDateTime.now()));

        completableFuture.join();
        System.out.println("Main thread finished! ");
    }

    @Test
    public void runAsyncException() {
        CompletableFuture<Void> completableFuture = CompletableFuture
                .runAsync(() -> {
                    System.out.println("First Runnable Task ... at " + LocalDateTime.now());
                    throw new IllegalArgumentException("Unknown exception ...");
                })
                .thenRun(() -> System.out.println("Second Runnable Task ... at " + LocalDateTime.now()))
                .exceptionally(e -> {
                    System.out.println("meet some exception");
                    e.printStackTrace(System.err);
                    return null;
                });

        completableFuture.join();
        System.out.println("Main thread finished! ");
    }

    @Test
    public void supplyAsync() {
        CompletableFuture<Void> completableFuture = CompletableFuture
                .supplyAsync( () -> {
                    System.out.println("First Callable Task ... at " + LocalDateTime.now());
                    try {
                        TimeUnit.MILLISECONDS.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return "First Result";
                })
                .thenAccept(r -> {
                    System.out.println("Second Callabe Task ... at " + LocalDateTime.now());
                    System.out.println("Received result from First Callable: " + r);
                });
        completableFuture.join();
        System.out.println("Main Thread Finished");
    }

    @Test
    public void supplyAsyncResult() throws ExecutionException, InterruptedException {
        CompletableFuture<String> completableFuture = CompletableFuture
                .supplyAsync( () -> {
                    System.out.println("First Callable Task ... at " + LocalDateTime.now());
                    try {
                        TimeUnit.MILLISECONDS.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return "First Result";
                })
                .thenApply(r -> {
                    System.out.println("Second Callabe Task ... at " + LocalDateTime.now());
                    System.out.println("Received result from First Callable: " + r);
                    return "Second Task Result";
                });
        System.out.println("Main Thread Finished with Result: " + completableFuture.get());
    }

    public static void supplyAsyncHandle() throws ExecutionException, InterruptedException {
        CompletableFuture<String> completableFuture = CompletableFuture
                .supplyAsync( () -> {
                    System.out.println("First Callable Task ... at " + LocalDateTime.now());
                    try {
                        TimeUnit.MILLISECONDS.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return "First Result";
                })
                .thenApply(r -> {
                    System.out.println("Second Callabe Task ... at " + LocalDateTime.now());
                    System.out.println("Received result from First Callable: " + r);
                    return "Second Task Result";
                })
                .handle((data, e) -> {
                    System.out.println("get result from first task, result: " + data);
                    if (e != null) {
                        e.printStackTrace();
                    }
                    return "handle over";
                })
                ;
        System.out.println("Main Thread Finished with Result: " + completableFuture.get());
    }

    @Test
    public void supplyAsyncHandleException() throws ExecutionException, InterruptedException {
        CompletableFuture<String> completableFuture = CompletableFuture
                .supplyAsync( () -> {
                    System.out.println("First Callable Task ... at " + LocalDateTime.now());
                    throw new IllegalArgumentException("Unkown Exception !!!");
                })
                .thenApply(r -> {
                    System.out.println("Second Callabe Task ... at " + LocalDateTime.now());
                    System.out.println("Received result from First Callable: " + r);
                    return "Second Task Result";
                })
                .handle((data, e) -> {
                    System.out.println("get result from first task, result: " + data);
                    if (e != null) {
                        e.printStackTrace();
                    }
                    return "handle over";
                })
                ;
        System.out.println("Main Thread Finished with Result: " + completableFuture.get());
    }
}

commonPool: CPU密集型任务使用

exectorService:  IO密集型任务使用

生产问题之CompletableFuture默认线程池踩坑,请务必自定义线程池 - 穿黑风衣的牛奶 - 博客园

CompletableFuture避坑1——需要自定义线程池 - 简书

自定义ThreadPool

https://blog.youkuaiyun.com/ALiangXiu/article/details/125007768

java - 使用CompletableFuture配合自定义线程池进行多任务并行处理 - 个人文章 - SegmentFault 思否

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值