Future Promise 并发模型

随着并发程序占据越来越多的生产比例,传统的基于线程和任务的开发方式越来越难以表达任务之间的关联关系。为了表达任务之间的状态依赖,常常需要引入某种范围的全局变量,导致程序意外的耦合或者出现难以排查的问题。简化复杂并发程序的开发的需求日渐迫切。在这样的背景下,业界结合学界的成果进行了若干种并发模型的尝试和落地,其中之一就是 Future Promise 模型。

本文首先介绍 Future Promise 模型的基本概念,然后以若干典型的实现讨论其并发模式,最后,结合其他并发模型以及相互的互操作讨论其特点和优劣势。

Future 的基本概念

通常,Future 和 Promise 两个名词在这个并发模型里是混用的,无论是 Future 还是 Promise 都指代一个用于取得计算结果的代理或者计算结果的容器。从容器的视角看,该容器初始并不包含结果,仅当计算完成时被填充结果;从代理的视角看,仅当计算完成时可以通过该代理获得其结果。

在有些实现中,这两个概念是区分的。这种情况下,Future 往往指的是一个结果的只读占位符,也就是说持有 Future 可以作为结果的占位符组合更多的计算逻辑,但不能对计算结果本身产生影响。Promise 则指的是一个可以单次写的结果的容器。

Future 的典型实现

上面提到,Future 可以作为结果的占位符组合其他计算逻辑,但是对于仅实现最简单的 Future 语义即未来完成的值的版本来说,这种组合并不轻松。

Java 1.5 版本的 Future

我们看到 Java 1.5 引入的最初版本的 Future 的定义。

public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
}

Future 取消的细节在《线程的取消和关闭》一文中有所涉及,主要要知道 Future 的取消是不可靠的,此外 cancel 接口可以被子类重写以完成一些状态修改和资源清理的工作。这里不再做展开。

除此以外,可以看到,除了生命周期的布尔判断之外,这个版本的 Future 实现仅支持唯一的 get 接口来阻塞地取得结果。如果结果暂未被填充进 Future 里,则阻塞等待。

这种接口设计导致如果我们通过 Future 表示某个计算的结果,为了组合这个结果,我们总需要最终通过 get 接口取得值,并将它和另一个值运行相关的计算。但是大多数并发程序并不希望这个阻塞等待发生在当前线程,于是我们需要在另一个线程中等待线程的结果。整体代码形如下面的代码块。

public Future<R> compose(Future<T> dep, Function<T, R> fn) {
    Future<Integer> result = executorService.submit(() -> {
        while (!dep.isDone()) {
            Thread.onSpinWait();
        }
        return fn.apply(dep.get());
    });
    
    return result;
}

当然,这样的代码也不复杂。但是一旦标准库没有提供,那么每个项目当中都要由开发者实现一遍。即使同一个团队的项目能够抽取出公共工具方法,但是世界范围内的开发者却很有可能开发出形形色色的实现,这其中很容易甚至是必然混入一些细微的不同,使得相互之间代码的交互变得复杂甚至不可能。从代码本身来说,我们需要再次向 ExecutorService 提交一个专门用于组合计算结果的作业,同时涉及到实际的阻塞过程,这无疑向开发者暴露了太多底层的细节,引入了更多的耦合和复杂度。

可以看到,上面这样的组合形式是直观而且通用的。同时,我们指出存在不同的此

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值