Java Future接口

Java Future接口,用户希望执行表示异步计算结果、检查计算是否完成、在必要时取消计算、检索计算结果等操作,可以使用能实现 java.util.concurrent.Future 接口的 CompletableFuture 类。

Java Future接口 问题描述

用户希望执行表示异步计算结果、检查计算是否完成、在必要时取消计算、检索计算结果等操作。

Java Future接口 解决方案

使用能实现 java.util.concurrent.Future 接口的 CompletableFuture 类。

Java Future接口 具体实例

在本书介绍的 Java 8 和 Java 9 新特性中,CompletableFuture 是一种非常有用的类。由于 CompletableFuture 类可以实现 Future 接口,我们有必要对这种接口的用法做一简要回顾。
Java 5 引入的 java.util.concurrent 包让开发人员可以在更高的抽象层次上操作并发,而不仅限于使用简单的 waitnotify 原语。java.util.concurrent 包定义了一种名为 ExecutorService 的接口,其 submit 方法传入 Callable,并返回包装所需对象的 Future
如例 9-15 所示,程序将任务提交给 ExecutorService 并打印字符串,然后在 Future 中检索值。

例 9-15 提交 Callable 并返回 Future

ExecutorService service = Executors.newCachedThreadPool();
Future<String> future = service.submit(new Callable<String>() {
    @Override
    public String call() throws Exception {
        Thread.sleep(100);
        return "Hello, World!";
    }
});
System.out.println("Processing...");
getIfNotCancelled(future);

例 9-16 显示了 getIfNotCancelled 方法的应用。

例 9-16 在 Future 中检索值

public void getIfNotCancelled(Future<String> future) {
    try {
        if (!future.isCancelled()) {           ➊
            System.out.println(future.get());  ➋
        } else {
            System.out.println("Cancelled");
        }
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
}

❶ 检查 Future 的状态
❷ 通过阻塞调用以检索 Future 的值
在本例中,isCancelled 方法的用途不言自明;get 方法用于在 Future 中检索值,该方法属于阻塞调用(blocking call),返回的是其内部的泛型类型;getIfNotCancelled 方法采用 try/catch 代码块处理声明的异常。
输出结果如下:

Processing...
Hello, World!

由于所提交的调用会立即返回 Future<String>,程序将马上打印“Processing…”。之后调用 get 代码块直到 Future 完成,并打印结果。
既然本书重点讨论 Java 8,我们不妨采用 lambda 表达式替换 Callable 接口的匿名内部类实现,如例 9-17 所示。

例 9-17 使用 lambda 表达式并检查 Future 是否完成

future = service.submit(() -> {        ➊
    Thread.sleep(10);
    return "Hello, World!";
});

System.out.println("More processing...");
while (!future.isDone()) {             ➋
    System.out.println("Waiting...");
}

getIfNotCancelled(future);

❶ 使用 lambda 表达式替换 Callable
❷ 等待 Future 完成
可以看到,除使用 lambda 表达式之外,程序还在 while 循环中调用 isDone 方法以轮询 Future,直至它完成。

在循环中使用 isDone 方法称为忙等待(busy waiting),由于该方法可能产生数百万次调用,通常属于应该避免的操作。12CompletableFuture 类(详见范例完成CompletableFuture
、范例多个CompletableFuture之间的协调一 与范例多个CompletableFuture之间的协调二可以在 Future 完成时提供更好的处理方式。

12某些情况下可能需要忙等待,如广泛用于操作系统内核的自旋锁(spinlock)。不过,自旋锁的持有时间过长会阻止其他线程运行,导致系统性能降低。——译者注

例 9-17 的输出结果如下:

More processing...
Waiting...
Waiting...
Waiting...
// 一直等待
Waiting...
Waiting...
Hello, World!

当某个 Future 完成时,程序显然需要一种更有效的方式来通知开发人员,计划将这个 Future 的结果用于其他操作时更是如此。CompletableFuture 类的作用就在于此。
此外,可以通过 Future 接口定义的 cancel 方法取消操作,如例 9-18 所示。

例 9-18 取消 Future

future = service.submit(() -> {
    Thread.sleep(10);
    return "Hello, World!";
});

future.cancel(true);

System.out.println("Even more processing...");

getIfNotCancelled(future);

输出结果如下:

Even more processing...
Cancelled

由于 CompletableFuture 类实现了 Future 接口,本范例讨论的所有方法同样适用于 CompletableFuture 类。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程