Lambda从入门到精通之二十八 使用Future异步编程

Future是什么
Future接口在Java 5中被引入,设计目的是为了实现异步计算,通过将一个耗时的计算操作分配到另一个线程计算,当前线程则继续向下执行自己的代码,在当前线程的某个位置,在获取Futrue的计算结果,从而实现了这种并发执行的异步计算效果。
举个例子,例如你要搬家,要将衣服和各种生活用品收纳到搬家的纸箱中,纸箱最后要用胶带粘好口避免搬家过程中散落,那么此时就可以一个人在家继续收拾屋子,将衣服等放到纸箱中,而买胶带的活就可以让另一个人出门去买,等胶带买回来,就可以将收拾好的箱子粘上了。

Future如何使用
要使用Future,通常你只需要将耗时的操作封装在一个Callable对象中,再将它提交给ExecutorService线程池即可。
看代码:

import java.util.Random;
import java.util.concurrent.*;

/**
 * Future
 * @author www.itzhimei.com
 */
public class FutureTest_1 {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(1);

        Callable<Integer> callable = () -> {
            Thread.sleep(2000);
            return new Random().nextInt();
        };

        Future<Integer> future = executorService.submit(callable);

        executorService.shutdown();
        Integer integer = future.get();
        System.out.println(integer);

    }
}

上面定义的Callable是有返回值的线程类型,和其相似的是Runnable,这是没有返回值的线程类型。
future.get()则是获取Callable的执行结果,我们可以看到在get方法执行之前,我们可以做其它的事情,这就实现了异步编程。

Future接口提供的方法:

boolean	cancel(boolean mayInterruptIfRunning)
尝试取消执行此任务。

V	get()
等待计算完成,然后检索其结果。

V	get(long timeout, TimeUnit unit)
如果需要等待最多在给定的时间计算完成,然后检索其结果(如果可用)。

boolean	isCancelled()
如果此任务在正常完成之前被取消,则返回 true 。

boolean	isDone()
返回 true如果任务已完成。

Future 接口的局限性
如果我们的代码中有多个比较耗时的计算逻辑,我们拆分成了多个任务去执行,都执行Future异步操作,然后在主线程等待结果。
这样的应用场景是多个耗时任务互不相关,但是如果多个任务相关关联,每一个任务都需要前一个任务的结果来辅助计算,那么Future就力不从心了,此时就需要使用CompletableFuture来解决更复杂的业务场景了。