CompletableFuture的async后缀函数与不带async的函数的区别

async函数

thenApply
thenApplyAsync

thenAccept
thenAcceptAsync

whenComplete
whenCompleteAsync
等等等等

不带async的函数的动作比较复杂

只要下面两个例子看懂了,就行了。

public class Lession07 {

    private final static Logger logger = LoggerFactory.getLogger(Lession07.class);

    public static void main(String[] args) throws Exception {
        CompletableFuture<Integer> f = new CompletableFuture<Integer>();

        new Thread(() -> {
            // 子线程A启动
            logger.info("子线程A启动");
            try {
                logger.info("子线程A沉睡5s");
                Thread.sleep(5000l);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            logger.info("子线程A令future完成");
            f.complete(100);  // 当子线程A执行到f.complete的时候,会去看是否有注册好的f的then或者when(非async的),如果有的话,会顺次去执行。
            logger.info("子线程A结束");
        }).start();;


        // 当前线程(主线程)执行到这里的时候,如果子线程还没有执行到f.complete(100),
        // 那么当前线程会把whenComplete事件注册起来,并且说好哪个线程执行了f.complete(100),
        // 哪个线程就负责执行whenComplete的内容。
        // 如果当前线程(主线程)执行到这里的时候,f.complete(100)已经被其他线程执行完毕了。
        // 那么只有当前线程自己来执行whenComplete里面的内容了。
        f.whenComplete((i, ex) -> {
            // 这个场景下,whenComplete的回调的执行线程会是子线程A
            logger.info("do something after complete begin");
            try {
                logger.info("沉睡10s");
                Thread.sleep(10000l);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            logger.info("do something after complete end");
        });


        logger.info("main over");
        System.in.read();

    }

}

以上程序打出的log如下:

20:33:40.389 [Thread-0] INFO com.wzm.opcua.lesson.Lession07 - 子线程A启动
20:33:40.395 [main] INFO com.wzm.opcua.lesson.Lession07 - main over
20:33:40.396 [Thread-0] INFO com.wzm.opcua.lesson.Lession07 - 子线程A沉睡5s
20:33:45.399 [Thread-0] INFO com.wzm.opcua.lesson.Lession07 - 子线程A令future完成
20:33:45.400 [Thread-0] INFO com.wzm.opcua.lesson.Lession07 - do something after complete begin
20:33:45.400 [Thread-0] INFO com.wzm.opcua.lesson.Lession07 - 沉睡10s
20:33:55.403 [Thread-0] INFO com.wzm.opcua.lesson.Lession07 - do something after complete end
20:33:55.403 [Thread-0] INFO com.wzm.opcua.lesson.Lession07 - 子线程A结束

让我们把主线程注册whenComplete的时机放慢一点,放到子线程A已经执行完f.complete之后。如下:

public class Lession07 {

    private final static Logger logger = LoggerFactory.getLogger(Lession07.class);

    public static void main(String[] args) throws Exception {
        CompletableFuture<Integer> f = new CompletableFuture<Integer>();

        new Thread(() -> {
            // 子线程A启动
            logger.info("子线程A启动");
            try {
                logger.info("子线程A沉睡5s");
                Thread.sleep(5000l);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            logger.info("子线程A令future完成");
            f.complete(100);  // 当子线程A执行到f.complete的时候,会去看是否有注册好的f的then或者when(非async的),如果有的话,会顺次去执行。
            logger.info("子线程A结束");
        }).start();;


        // 当前线程(主线程)执行到这里的时候,如果子线程还没有执行到f.complete(100),
        // 那么当前线程会把whenComplete事件注册起来,并且说好哪个线程执行了f.complete(100),
        // 哪个线程就负责执行whenComplete的内容。
        // 如果当前线程(主线程)执行到这里的时候,f.complete(100)已经被其他线程执行完毕了。
        // 那么只有当前线程自己来执行whenComplete里面的内容了。

        try {
            logger.info("主线程沉睡10s");
            Thread.sleep(10000l);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        f.whenComplete((i, ex) -> {
            // 这个场景下,whenComplete的回调的执行线程会是主线程
            logger.info("do something after complete begin");
            try {
                logger.info("沉睡10s");
                Thread.sleep(10000l);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            logger.info("do something after complete end");
        });


        logger.info("main over");
        System.in.read();

    }

}

log输出如下:

20:41:40.200 [Thread-0] INFO com.wzm.opcua.lesson.Lession07 - 子线程A启动
20:41:40.203 [main] INFO com.wzm.opcua.lesson.Lession07 - 主线程沉睡10s
20:41:40.205 [Thread-0] INFO com.wzm.opcua.lesson.Lession07 - 子线程A沉睡5s
20:41:45.207 [Thread-0] INFO com.wzm.opcua.lesson.Lession07 - 子线程A令future完成
20:41:45.207 [Thread-0] INFO com.wzm.opcua.lesson.Lession07 - 子线程A结束
20:41:50.212 [main] INFO com.wzm.opcua.lesson.Lession07 - do something after complete begin
20:41:50.212 [main] INFO com.wzm.opcua.lesson.Lession07 - 沉睡10s
20:42:00.215 [main] INFO com.wzm.opcua.lesson.Lession07 - do something after complete end
20:42:00.215 [main] INFO com.wzm.opcua.lesson.Lession07 - main over

结论

f的whenComplete的内容由哪个线程来执行,取决于哪个线程X执行了f.complete()。但是当X线程执行了f.complete()的时候,whenComplete还没有被执行到的时候(就是事件还没有注册的时候),那么X线程就不会去同步执行whenComplete的回调了。这个时候哪个线程执行到了whenComplete的事件注册的时候,就由哪个线程自己来同步执行whenComplete的事件内容。

而whenCompleteAsync的场合,就简单很多。一句话就是线程池里面拿一个空的线程或者新启一个线程来执行回调。和执行f.complete的线程以及执行whenCompleteAsync的线程无关。

  • 9
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当一个函数只加上async而没有加上await时,它仍然是一个异步函数,但它并不会等待任何Promise对象的完成。这意味着,即使函数内部有异步操作,它也会立即返回一个Promise对象,而不会等待异步操作的结果。这在某些情况下可能是有用的,比如在一个函数内部同时执行多个异步操作,并在它们都完成后再处理结果。另外,当一个函数被标记为async时,它的返回值将始终是一个Promise对象,即使函数内部没有使用await关键字。因此,调用这个函数时,我们可以使用then()方法来处理返回的Promise对象,以获取最终的结果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [浅谈async函数await用法](https://blog.csdn.net/sinat_28585351/article/details/107630429)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [详解Node.js中的Async和Await函数](https://download.csdn.net/download/weixin_38724154/13762598)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值