iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java8 自定义CompletableFuture的原理解析
  • 877
分享到

Java8 自定义CompletableFuture的原理解析

2024-04-02 19:04:59 877人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录Java8 自定义CompletableFuture原理CompleteFuture简单使用下面简单介绍用法Java8 自定义CompletableFuture原理 Future

Java8 自定义CompletableFuture原理

Future 接口 的局限性有很多,其中一个就是需要主动的去询问是否完成,如果等子线程的任务完成以后,通知我,那岂不是更好?


public class FutureInAction3 {
    public static void main(String[] args) {
        Future<String> future = invoke(() -> {
            try {
                Thread.sleep(10000L);
                return "I am Finished.";
            } catch (InterruptedException e) {
                return "I am Error";
            }
        });
        future.setCompletable(new Completable<String>() {
            @Override
            public void complete(String s) {
                System.out.println("complete called ---- " + s);
            }
            @Override
            public void exception(Throwable cause) {
                System.out.println("error");
                cause.printStackTrace();
            }
        });
        System.out.println("....do something else .....");
        System.out.println("try to get result ->" + future.get());
    }
    private static <T> Future<T> invoke(Callable<T> callable) {
        AtomicReference<T> result = new AtomicReference<>();
        AtomicBoolean finished = new AtomicBoolean(false);
        Future<T> future = new Future<T>() {
            private Completable<T> completable;
            @Override
            public T get() {
                return result.get();
            }
            @Override
            public boolean isDone() {
                return finished.get();
            }
            // 设置完成
            @Override
            public void setCompletable(Completable<T> completable) {
                this.completable = completable;
            }
            // 获取
            @Override
            public Completable<T> getCompletable() {
                return completable;
            }
        };
        Thread t = new Thread(() -> {
            try {
                T value = callable.action();
                result.set(value);
                finished.set(true);
                if (future.getCompletable() != null)
                    future.getCompletable().complete(value);
            } catch (Throwable cause) {
                if (future.getCompletable() != null)
                    future.getCompletable().exception(cause);
            }
        });
        t.start();
        return future;
    }
    private interface Future<T> {
        T get();
        boolean isDone();
        //  1
        void setCompletable(Completable<T> completable);
        //  2
        Completable<T> getCompletable();
    }
    private interface Callable<T> {
        T action();
    }
    // 回调接口
    private interface Completable<T> {
        void complete(T t);
        void exception(Throwable cause);
    }
}

在这里插入图片描述

CompleteFuture简单使用

Java8 中的 completeFuture 是对 Future 的扩展实现, 主要是为了弥补 Future 没有相应的回调机制的缺陷.

我们先看看 Java8 之前的 Future 的使用


package demos;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Demo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService cachePool = Executors.newCachedThreadPool();
        Future<String> future = cachePool.submit(() -> {
            Thread.sleep(3000);
            return "异步任务计算结果!";
        });
        // 提交完异步任务后, 主线程可以继续干一些其他的事情.
        doSomeThingElse();
        // 为了获取异步计算结果, 我们可以通过 future.get 和 轮询机制来获取.
        String result;
        // Get 方式会导致当前线程阻塞, 这显然违背了异步计算的初衷.
        // result = future.get();
        // 轮询方式虽然不会导致当前线程阻塞, 但是会导致高额的 CPU 负载.
        long start = System.currentTimeMillis();
        while (true) {
            if (future.isDone()) {
                break;
            }
        }
        System.out.println("轮询耗时:" + (System.currentTimeMillis() - start));        
        result = future.get();
        System.out.println("获取到异步计算结果啦: " + result);
        cachePool.shutdown();
    }
    private static void doSomeThingElse() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("我的最重要的事情干完了, 我要获取异步计算结果来执行剩下的事情.");
    }
}

输出:

我的最重要的事情干完了, 我要获取异步计算结果来执行剩下的事情.
轮询耗时:2000
获取到异步计算结果啦: 异步任务计算结果!

Process finished with exit code 0

从上面的 Demo 中我们可以看出, future 在执行异步任务时, 对于结果的获取显的不那么优雅, 很多第三方库就针对 Future 提供了回调式的接口以用来获取异步计算结果, 如Google的: ListenableFuture, 而 Java8 所提供的 CompleteFuture 便是官方为了弥补这方面的不足而提供的 api.

下面简单介绍用法


package demos;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CompleteFutureDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<String> completableFutureOne = new CompletableFuture<>();
        ExecutorService cachePool = Executors.newCachedThreadPool();
        cachePool.execute(() -> {
            try {
                Thread.sleep(3000);
                completableFutureOne.complete("异步任务执行结果");
                System.out.println(Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        // WhenComplete 方法返回的 CompletableFuture 仍然是原来的 CompletableFuture 计算结果.
        CompletableFuture<String> completableFutureTwo = completableFutureOne.whenComplete((s, throwable) -> {
            System.out.println("当异步任务执行完毕时打印异步任务的执行结果: " + s);
        });
        // ThenApply 方法返回的是一个新的 completeFuture.
        CompletableFuture<Integer> completableFutureThree = completableFutureTwo.thenApply(s -> {
            System.out.println("当异步任务执行结束时, 根据上一次的异步任务结果, 继续开始一个新的异步任务!");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return s.length();
        });
        System.out.println("阻塞方式获取执行结果:" + completableFutureThree.get());
        cachePool.shutdown();
    }
}

从上面的 Demo 中我们主要需要注意 thenApply 和 whenComplete 这两个方法, 这两个方法便是 CompleteFuture 中最具有意义的方法, 他们都会在 completeFuture 调用 complete 方法传入异步计算结果时回调, 从而获取到异步任务的结果.

相比之下 future 的阻塞和轮询方式获取异步任务的计算结果, CompleteFuture 获取结果的方式就显的优雅的多。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: Java8 自定义CompletableFuture的原理解析

本文链接: https://www.lsjlt.com/news/156429.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java8 自定义CompletableFuture的原理解析
    目录Java8 自定义CompletableFuture原理CompleteFuture简单使用下面简单介绍用法Java8 自定义CompletableFuture原理 Future...
    99+
    2024-04-02
  • Java8自定义CompletableFuture的原理是什么
    本篇内容主要讲解“Java8自定义CompletableFuture的原理是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java8自定义CompletableFuture的原理是什么”吧!...
    99+
    2023-06-25
  • 解析Java8 Stream原理
    目录一、前言二、Stream流水线解决方案2.1、操作如何记录2.2、操作如何叠加2.3、叠加之后的操作如何执行一、前言 首先我们先看一个使用Stream API的示例,具体代码如下...
    99+
    2024-04-02
  • 详解Java8 CompletableFuture的并行处理用法
    目录前言场景用法1、在线API2、编写在线API查询3、编写查询服务4、编写测试接口5、效果6、CompletableFuture并行查询7、编写测试接口8、CompletableF...
    99+
    2024-04-02
  • Java CompletableFuture实现原理分析详解
    目录简介CompletableFuture类结构CompletableFuture回调原理CompletableFuture异步原理总结简介 前面的一篇文章你知道Java8并发新特性...
    99+
    2024-04-02
  • javaSE基础java自定义注解原理分析
    目录1. 从注释的角度来理解注解2.提出问题3.编写注解4.通过Java反射获取方法的注解信息结束注解在JavaSE中算是比较高级的一种用法了,为什么要学习注解,我想大概有以下几个原...
    99+
    2024-04-02
  • Java7和Java8中的ConcurrentHashMap原理解析
    目录Java7 中 ConcurrentHashMap初始化put 过程分析初始化槽: ensureSegment获取写入锁: scanAndLockForPut扩容: rehash...
    99+
    2024-04-02
  • Docker网络原理及自定义网络详细解析
    Docker在宿主机上虚拟了一个网桥,当创建并启动容器的时候,每一个容器默认都会被分配一个跟网桥网段一致的ip,网桥作为容器的网关,网桥与每一个容器联通,容器间通过网桥可以通信。由于...
    99+
    2024-04-02
  • 云原生Docker容器自定义DNS解析
    目录描述实现方式docker-compose配置【推荐】进入容器内部修改docker run 命令的时候添加docker build构建镜像时添加结尾总结 描述 在特定的情...
    99+
    2023-02-21
    docker设置dns docker配置dns docker容器自定义dns
  • Android自定义View原理(实战)
    目录1、为什么需要自定义View2、自定义View的基本方法3、自定义View的属性如何操作4、View的视图结构5、View的坐标系6、View树的绘制流程6.1 measure过...
    99+
    2024-04-02
  • golang函数自定义实现原理
    在 go 语言中,可自定义函数的实现原理如下:定义函数签名:func () 赋予函数值:函数作为值类型,可赋值给变量、传递或返回。调用函数:使用圆括号括起来的函数名后跟参数列表。实战案例...
    99+
    2024-04-26
    函数 golang
  • 探析静态定位的定义及工作原理
    剖析静态定位的定义和原理 静态定位是指在地理位置或其他坐标系统中通过使用测量仪器、卫星导航系统或其他技术手段来精确测量和确定物体的位置、方向和速度的过程。它可以应用于许多领域,包括航海、航空、地理勘测、地理信息系统等。静态定位的...
    99+
    2024-01-18
  • 浅析Java自定义注解的用法
    目录注解定义注解注解处理器运行时解析注解编译时解析注解总结注解 注解为我们在代码中添加信息提供一种形式化的方法,使我们可以在源码、编译时、运行时非常方便的使用这些数据。 注解是在JA...
    99+
    2023-03-21
    Java自定义注解使用 Java自定义注解 Java 注解
  • 深入解析Vue的自定义指令
    目录介绍​指令钩子​钩子参数​简化形式​对象字面量​在组件上使用​介绍​ 除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之...
    99+
    2023-05-18
    Vue 指令 Vue自定义指令
  • 深入理解React的自定义Hook
    自定义 Hooks 的核心是共享组件之间的逻辑。使用自定义 Hooks 能够减少重复的逻辑,更重要的是,自定义 Hooks 内部的代码描述了它们想做什么,而不是如何做。当你将逻辑提取到自定义Hooks 中时,你可以隐藏如何处理某些"...
    99+
    2023-05-14
    前端 代码规范 React.js
  • 云原生Docker容器自定义DNS解析的方法是什么
    这篇文章主要讲解了“云原生Docker容器自定义DNS解析的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“云原生Docker容器自定义DNS解析的方法是什么”吧!描述在特定的情况下...
    99+
    2023-07-05
  • spring 自定义让@Value被解析到
    目录spring 自定义让@Value解析到背景实现原理Spring4自定义@Value功能演示@Value的用法我们定义一个注解spring 自定义让@Value解析到 @Valu...
    99+
    2024-04-02
  • 自定义注解和springAOP捕获Service层异常并处理自定义异常的示例分析
    这篇文章主要为大家展示了“自定义注解和springAOP捕获Service层异常并处理自定义异常的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“自定义注解和springAOP捕获Serv...
    99+
    2023-06-15
  • Java如何自定义DNS解析器
    本篇内容介绍了“Java如何自定义DNS解析器”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!前言:最近终于用上了高性能的测试机(54C96G...
    99+
    2023-06-29
  • 基于自定义Toast全面解析
    Toast一般用来显示一行文字,用法比较固定:Toast.makeText(Context context,String message,int duration);...
    99+
    2023-05-30
    自定义 toast st
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作