• Java8-CompletableFuture的使用


    Future接口

    Future接口是Java并发编程中的一个接口,它表示一个可能还没有完成的异步操作的结果。Future接口的主要作用是提供一种机制,允许调用者在某个异步操作完成后取得其结果

    @Data
    @AllArgsConstructor
    public class MedalInfo {
        public String id;
        public String name;
    }
    
    @Data
    @AllArgsConstructor
    public class UserInfo {
        public String id;
        public String name;
        public int age;
    }
    /**
     * 勋章服务
     */
    public class MedalService {
    
        public MedalInfo getMedalInfo(long userId){
            try {
                Thread.sleep(500); //模拟调用耗时
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return new MedalInfo("666", "守护勋章");
        }
    }
    /**
     * 用户服务
     */
    public class UserInfoService {
    
        public UserInfo getUserInfo(Long userId){
            try {
                Thread.sleep(300);//模拟调用耗时
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return new UserInfo("666", "捡田螺的小男孩", 27); //一般是查数据库,或者远程调用返回的
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    用Future 模拟同时获取 用户和勋章

    public class FutureTest {
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
    
            ExecutorService executorService = Executors.newFixedThreadPool(10);
    
            UserInfoService userInfoService = new UserInfoService();
            MedalService medalService = new MedalService();
            long userId = 666L;
            long startTime = System.currentTimeMillis();
    
            //调用用户服务获取用户基本信息
            FutureTask<UserInfo> userInfoFutureTask = new FutureTask<>(new Callable<UserInfo>() {
                @Override
                public UserInfo call() throws Exception {
                    return userInfoService.getUserInfo(userId);
                }
            });
            executorService.submit(userInfoFutureTask);
    
            Thread.sleep(300); //模拟主线程其它操作耗时
    
            FutureTask<MedalInfo> medalInfoFutureTask = new FutureTask<>(new Callable<MedalInfo>() {
                @Override
                public MedalInfo call() throws Exception {
                    return medalService.getMedalInfo(userId);
                }
            });
            executorService.submit(medalInfoFutureTask);
    
            UserInfo userInfo = userInfoFutureTask.get();//获取个人信息结果
            MedalInfo medalInfo = medalInfoFutureTask.get();//获取勋章信息结果
            executorService.shutdown(); // 关闭ExecutorService
    
            System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    基本概念

    CompletableFuture 是 Java 8 引入的一个类,用于处理异步编程和并发操作。它提供了一种简洁、强大和灵活的方式来处理异步任务。

    CompletableFuture 可以看作是一个可以执行异步操作的容器,可以将多个异步任务组合在一起,以便在一个或多个任务完成时执行特定操作。

    CompletableFuture 类提供了一系列的方法,用于创建 CompletableFuture 实例、以及对它们进行组合和操作。一些常用的方法包括:

    • supplyAsync():用于执行一个异步任务并返回结果。
    • thenApply():用于在一个 CompletableFuture 上执行一个操作,并返回一个新的 CompletableFuture 对象。
    • thenCompose():用于将两个 CompletableFuture 对象进行组合,将一个 CompletableFuture 的结果作为参数传递给另一个 CompletableFuture。
    • thenCombine():用于将两个 CompletableFuture 对象进行组合,并将它们的结果进行合并。
    • whenComplete():用于注册一个回调方法,在 CompletableFuture 执行完成时执行该回调方法。
    • handle():用于注册一个回调方法,可以对成功结果和异常进行处理。

    CompletableFuture 的一个重要特点是它支持链式调用,可以通过不断地调用上述方法组合多个 CompletableFuture 对象,形成一条执行流水线。

    通过使用 CompletableFuture,可以更简洁地处理异步编程和并发操作,提高代码的可读性和可维护性。同时,CompletableFuture 还提供了一些其他高级特性,如超时机制和异常处理,使得处理异步任务更加灵活和强大。

    简单示例

    public class Test2 {
        public static void asyncCallback() throws ExecutionException, InterruptedException {
    
            CompletableFuture<Integer> task = CompletableFuture.supplyAsync(new Supplier<String>() {
                @Override
                public String get() {
                    System.out.println(Thread.currentThread().getName() + "supplyAsync");
                    return "123";
                }
            }).thenApply(number -> {
                System.out.println(Thread.currentThread().getName() + "thenApply1");
                return Integer.parseInt(number);
            }).thenApply(number -> {
                System.out.println(Thread.currentThread().getName() + "thenApply2");
                return number * 2;
            });
    
            task.thenRun(()->{
                System.out.println(Thread.currentThread().getName()+"thenRun: 收尾任务");
            });
    
            System.out.println(Thread.currentThread().getName() + " => " + task.get());
    
        }
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            asyncCallback();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    修改Future 模拟同时获取用户和勋章

    public class FutureTest1 {
    
        public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
    
            UserInfoService userInfoService = new UserInfoService();
            MedalService medalService = new MedalService();
            long userId =666L;
            long startTime = System.currentTimeMillis();
    
            //调用用户服务获取用户基本信息
            CompletableFuture<UserInfo> completableUserInfoFuture = CompletableFuture.supplyAsync(() -> userInfoService.getUserInfo(userId));
    
            Thread.sleep(300); //模拟主线程其它操作耗时
    
            CompletableFuture<MedalInfo> completableMedalInfoFuture = CompletableFuture.supplyAsync(() -> medalService.getMedalInfo(userId));
    
            UserInfo userInfo = completableUserInfoFuture.get(2, TimeUnit.SECONDS);//获取个人信息结果
            MedalInfo medalInfo = completableMedalInfoFuture.get();//获取勋章信息结果
            System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    代码上简洁很多,同样也能实现Future 的功能。

  • 相关阅读:
    统计信号处理基础 习题解答10-6
    Java NIO :如何为通道注册多个事件及多线程处理 Accetp 请求
    Spring-IOC控制反转
    Python学习基础笔记七十一——模块和库2
    彻底弄懂C#中delegate、event、EventHandler、Action、Func的使用和区别
    JVM (四)GC过程
    乐鑫科技收购创新硬件公司 M5Stack 控股权
    Java 实现最大公约数与最小公倍数
    chrome 扩展 popup 弹窗的使用
    Java理清JDK、JRE、JVM之间什么关系?如何做到一次编译到处执行的?
  • 原文地址:https://blog.csdn.net/u011067966/article/details/138156154