全栈笔记(一)Promise对比CompleteableFuture
前言
此篇是开启【全栈笔记】系列的第一篇文章,记录软件开发过程中遇到的相似技术点来做个总结。今天我们要对比的是 CompleteableFuture 与 Promise。本文适合有一定 Java 与 JavaScript 基础的同学阅读。
简单对比
Promise
1 | let p = new Promise((resolve, reject) => { |
CompleteableFuture
1 | CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> { |
上面两段代码相似度很高,是不同语言的异步编程。Promise 对应 CompletableFuture,p.then 对应 cf.thenAccept,p.catch 对应 cf.exceptionally。
这里再列举一个相似的用法。
Promise.race
1 | const p1 = new Promise((resolve) => { |
CompletableFuture.anyOf
1 | public static void sleepSeconds(int seconds) { |
Promise.race方法只要p1、p2、p3之中有任何一个实例率先执行成功,p的状态就跟着改变。就像他的方法名race一样,p1,p2,p3赛跑返回最先执行完(最先跑过终点)的值。CompletableFuture.anyOf和Promise.race效果相同。
Promise.all和CompletableFuture.allOf也是相同的。只有等p1,p2,p3全部执行完之后才返回他们三者的值。
异步与多线程
什么是异步
先来看下同步的定义,「一定要等任务执行完了,得到结果,才执行下一个任务」。异步就是「不等任务执行完,直接执行下一个任务」。JS运行在浏览器中是单线程的,注意浏览器是多线程。有些同学会说异步是同时做两件事,但其实 JS 引擎不会这样,异步意味着不等待任务结束,并没有强制要求两个任务「同时」进行。
强调的是不等待,通常异步都是与同步做比较
什么是多线程
多线程是指每条线程可以并行「同时」执行不同的任务。
强调的是同时执行
发现在实际开发中很多同学会混淆异步与多线程的概念。Promise与CompleteableFuture都属于异步编程,但是他们实现异步的方式不同,Promise是Event Loop的运行机制实现的异步,CompleteableFuture是用多线程实现的异步。异步是一种目的。多线程是实现目的的一种方式。
CompleteableFuture的thenXXX方法中打印线程的名称,有时会发现他是在另一个线程中执行的。
总结
promise作为异步操作的API,给前端开发带来了不少便利,有效的解决了回调地狱的问题,更重要的是让代码变的更加优雅。CompletableFuture是JDK1.8的时候加入的,在Future的基础上,增加了通知回调的功能(实现CompletionStage接口)。很多RPC框架中都有对CompletableFuture的支持,因为CompletableFuture是Java原生支持的有更好的性能和兼容,更重要的在是业务逻辑中没有代码侵入。