从多线程设计模式到对 CompletableFuture 的应用

大家好,我是 方圆。最近在开发 延保服务 频道页时,为了提高查询效率,使用到了多线程技术。为了对多线程方案设计有更加充分的了解,在业余时间读完了《图解 Java 多线程设计模式》这本书,觉得收获良多。本篇文章将介绍其中提到的 Future 模式,以及在实际业务开发中对该模式的应用,而这些内容对于本书来说只是冰山一角,还是推荐大家有时间去阅读原书。

1. Future 模式:“先给您提货单”

我们先来看一个场景:假如我们去蛋糕店买蛋糕,下单后,店员会递给我们提货单并告知“请您傍晚来取蛋糕”。到了傍晚我们拿着提货单去取蛋糕,店员会先和我们说“您的蛋糕已经做好了”,然后将蛋糕拿给我们。

如果将下单蛋糕到取蛋糕的过程抽象成一个方法的话,那么意味着这个方法需要花很长的时间才能获取执行结果,与其一直等待结果,不如先拿着一张“提货单”,到我们需要取货的时候,再通过它去取,而获取“提货单”的过程是几乎不耗时的,而这个提货单对象就被称为 Future,后续便可以通过它来获取方法的返回值。用 Java 来表示这个过程的话,需要使用到 FutureTaskCallable 两个类,如下:

public class Example {
   
   
    public static void main(String[] args) throws InterruptedException, ExecutionException {
   
   
        // 预定蛋糕,并定义“提货单”
        System.out.println("我:预定蛋糕");
        FutureTask<String> future = new FutureTask<>(() -> {
   
   
            System.out.println("店员:请您傍晚来取蛋糕");
            Thread.sleep(2000);
            System.out.println("店员:您的蛋糕已经做好了");

            return "Holiland";
        });
        // 开始做蛋糕
        new Thread(future).start();

        // 去做其他事情
        Thread.sleep(1000);
        System.out.println("我:忙碌中...");
        // 取蛋糕
        System.out.println("我:取蛋糕 " + future.get());
    }
}

// 运行结果:
// 我:预定蛋糕
// 店员:请您傍晚来取蛋糕
// 我:忙碌中...
// 店员:您的蛋糕已经做好了
// 我:取蛋糕 Holiland

方法的调用者可以将任务交给其他线程去处理,无需阻塞等待方法的执行,这样调用者便可以继续执行其他任务,并能通过 Future 对象获取执行结果。

它的运行原理如下:创建 FutureTask 实例时,Callable 对象会被传递给构造函数,当线程调用 FutureTaskrun 方法时,Callable 对象的 call 方法也会被执行。调用 call 方法的线程会同步地获取结果,并通过 FutureTaskset 方法来记录结果对象,如果 call 方法执行期间发生了异常,则会调用 setException 方法记录异常。最后,通过调用 get 方法获取方法的结果,注意这里可能会抛出方法执行时产生的异常

    public void run() {
   
   
        // ...
        try {
   
   
            // “提货任务”
            Callable<V> c = callable;
            if (c != null && state == NEW) {
   
   
                V result;
                boolean ran;
                try {
   
   
                    // 调用 callable 的 call 方法
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
   
   
                    result = null;
                    ran = false;
                    // 捕获并设置异常
                    setException(ex);
                }
                if (ran)
                    // 为结果赋值
                    set(result);
            }
        } finally {
   
   
            // ...
        }
    }

    protected void set(V v) {
   
   
        if (STATE.compareAndSet(this, NEW, COMPLETING))
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方圆想当图灵

嘿嘿,小赏就行,不赏俺也不争你

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值