笔记 11 · Future 任务异步执行

本文深入探讨了Java中的Future接口及其在异步计算中的应用。FutureTask和CompletableFuture作为Future的实现,提供了任务取消、状态检查和结果获取等功能。通过实例展示了如何避免阻塞,利用CompletableFuture实现阶段性和回调操作,从而提高程序的并发性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Future代表了异步计算的结果,提供诸多方法检查异步计算是否完成,是否需要等待,以及获取结果。结果只能通过 get() 方法获取。
如果我们调用了get方法,但异步任务却并未完成,会陷入阻塞状态,直到异步计算结束。

表示未来异步计算的结果。提供了检查计算是否完成、等待其完成以及检索计算结果的方法。只有在计算完成时,才能使用方法get检索结果,必要时阻塞,直到它准备就绪。可通过取消方法取消执行任务。一旦计算完成,就不能取消计算。如果为了可取消性而想使用Future,但不提供可用的结果,可以声明Future<?>并作为基础任务的结果返回null。

方法

boolean cancel(boolean mayInterruptIfRunning);

  • 取消方法执行。
  • 如果任务已完成、已取消或由于其他原因无法取消,则此尝试将失败。如果成功,并且在调用cancel时此任务尚未启动,则此任务不应运行。如果任务已经启动,那么maybuitFrunning 参数确定执行此任务的线程是否应该被中断以试图停止任务。

boolean isCancelled();

  • 任务是否已经被取消,如果此任务在正常完成之前被取消,则返回true。
  • 如果cancel() 返回true,则对isCanceled的后续调用将始终返回true。

boolean isDone();

  • 如果此任务已完成,则返回true。完成可能是由于正常终止、异常或取消造成的——在所有这些情况下,此方法都将返回true。

V get() throws InterruptedException, ExecutionException;

  • 等待任务完成,返回异步任务结果。会陷入阻塞状态。

V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException;

实现类

FutureTask implements RunnableFuture

一种可取消的异步计算。这个类提供了Future的一个基本实现,提供了启动和取消计算、查询计算是否完成以及检索计算结果的方法。只有在计算完成时才能检索结果;如果计算尚未完成,get方法将阻塞。一旦计算完成,就不能重新启动或取消计算(除非使用runAndReset调用计算)。
FutureTask可用于包装可调用或可运行的对象。因为FutureTask实现Runnable,FutureTask可以提交给执行者执行。

public static void main(String[] args) {
    // 定义一个任务
    Callable<Integer> callable = () -> {
        System.out.println("pre execution");
        int randomNum = new Random().nextInt(500);
        System.out.println("post execution");
        return randomNum;
    };

    // 包装成异步任务
    FutureTask<Integer> futureTask = new FutureTask<>(callable);
    new Thread(futureTask).start();

    try {
        // 异步任务未完成,会陷入阻塞状态,直到异步计算结束。
        System.out.println(futureTask.get());
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
}
CompletableFuture implements Future, CompletionStage

避免使用future的get() 方法,发生阻塞的情况。

注:completionStage.java :一个任务可能会有多个阶段,当第一个阶段完成后,触发第二个阶段。以此类推。

演示 - 阶段性完成。 hello world

String join = CompletableFuture.supplyAsync(() -> "hello").thenApplyAsync(value -> value + " world").join();
System.out.println(join);
System.out.println("-----------------");

String result2 = CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "hello";
}).thenCombine(CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "world";
}), (s1, s2) -> s1 + " " + s2).join();
System.out.println(result2);

演示 - 完成计算结果后,回调。保证获取结果时的异步性。避免阻塞。

CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
    try {
        TimeUnit.MILLISECONDS.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("任务完成");
});

// 回调,不会阻塞
completableFuture.whenComplete((t, action) -> System.out.println("执行完成!"));
System.out.println("主线程执行完毕");
try {
    // 推迟主线程结束时间,方便观察 子线程执行过程
    TimeUnit.MILLISECONDS.sleep(4000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

在这里插入图片描述

注:资料主要来源【张龙

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值