news 2026/4/16 14:28:42

聊聊 Future 接口

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
聊聊 Future 接口

一、背景介绍

在前几篇线程系列文章中,我们介绍了线程池的相关技术,任务执行类只需要实现Runnable接口,然后交给线程池,就可以轻松的实现异步执行多个任务的目标,提升程序的执行效率,比如如下异步执行任务下载。

// 创建一个线程池 ExecutorService executor = Executors.newFixedThreadPool(2); // 提交任务 executor.submit(new Runnable() { @Override public void run() { // 执行下载某文件任务 System.out.println("执行下载某文件任务"); } });

而实际上Runnable接口并不能满足所有的需求,比如有些场景下,我们想要获取任务执行的返回结果,Runnable接口因为无返回值,只能想办法通过额外的方式来写入和读取,操作起来十分不便。

因此,从 JDK 1.5 开始,Java 标准库提供了一个Callable接口,与Runnable接口相比,它的方法上多了一个返回值;同时Callable是一个泛型接口,可以返回指定类型的结果,比如如下的实现类!

public class Task implements Callable<String> { @Override public String call() throws Exception { // 执行下载某文件任务 System.out.println("执行下载某文件任务"); return "xxx"; } }

问题来了,如何获取异步执行的结果呢?

在 JDK 1.5 中,Java 标准库还提供了一个Future接口,它可以用来获取异步执行的结果。

下面我们一起来了解一下这个Future接口!

二、Future

Future接口,表示一个可能还没有完成异步任务的结果,它提供了检查任务是否已完成、以及等待任务完成并获取结果等方法。

如果看过ExecutorService.submit()方法,会发现它的返回参数都是Future类型,Future类型的实例可以用来获取异步任务执行的结果。

下面我们先来看一个简单的示例,以便于更好的理解!

public class Task implements Callable<String> { @Override public String call() throws Exception { // 执行下载某文件任务,并返回文件名称 System.out.println("thread name:" + Thread.currentThread().getName() + " 开始执行下载任务"); return "xxx.png"; } }
public class FutureTest { public static void main(String[] args) throws Exception { // 创建一个线程池 ExecutorService executor = Executors.newFixedThreadPool(1); // 初始化一个任务 Callable<String> task = new Task(); // 提交任务并获得Future的实例 Future<String> future = executor.submit(task); // 从Future获取异步执行返回的结果(可能会阻塞等待结果) String result =future.get(); System.out.println("任务执行结果:" + result); // 任务执行完毕之后,关闭线程池(可选) executor.shutdown(); } }

输出结果如下:

thread name:pool-1-thread-1 开始执行下载任务 任务执行结果:xxx.png

从以上的示例可以清晰的看到,当需要获取异步线程的执行结果返回值时,通常需要搭配使用FutureCallable接口来实现,大体可以用如下步骤来概括:

  • 1.首先提交一个实现Callable接口的任务到线程池中

  • 2.然后获取一个Future类型的对象

  • 3.最后在主线程中调用Future对象的get()方法,如果异步任务执行完成,就可以直接获得结果;如果异步任务执行没有完成,get()方法会阻塞,直到任务执行完成后才能获取结果

分析源码你会发现,Callable接口主要用途是定义一个支持返回结果的方法;重点实现主要集中在Future接口上。

下面我们重点来看下Future接口方法!

2.1、Future 接口方法

方法

描述

get()

获取结果(会阻塞等待)

get(long timeout, TimeUnit unit)

在指定的时间内获取结果,如果超时,会抛异常并退出等待状态

cancel(boolean mayInterruptIfRunning)

尝试取消当前任务,当传入参数为true时,表示尝试中断任务的执行,false表示不中断,继续执行直到完成,如果取消成功,返回true;反之false

isCancelled()

判断任务是否已取消

isDone()

判断任务是否已完成

2.2、Future 接口实现类

Future本质其实是一个接口,并不是具体的实现类,真正负责工作的还是它的实现类来完成。

我们还是以上文的线程池ExecutorService.submit()方法为例,看看它用的是哪种实现类!

分析一下源码,会发现线程池用的实现类是FutureTask,关键核心源码如下:

protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { return new FutureTask<T>(callable); }

FutureTask类是一个实现了Future接口所有功能的具体类,可直接使用它来实现获取异步任务执行的结果值。

FutureTask的工作原理其实也并不复杂,它接受一个Callable或者Runnable对象作为参数,然后在线程池执行器中执行该任务,最后通过get()方法可以同步等待获取任务的执行结果。

真正起到关键作用的是,在FutureTask内部,封装了一个状态变量,用于记录任务的状态(等待、运行、完成、取消等),以及任务执行结果或异常信息,通过该状态变量,我们可以判断任务是否已完成、以及获取任务的执行结果等信息。

因为FutureTask也实现了Runnable接口,因此我们也可以将FutureTask作为任务,提交给线程池执行器。

具体示例如下:

public class FutureTest { public static void main(String[] args) throws Exception { // 1.创建一个线程池 ExecutorService executor = Executors.newFixedThreadPool(1); // 2.初始化一个任务 Callable<String> callable = new Task(); // 3.创建FutureTask对象 FutureTask<String> futureTask = new FutureTask<>(callable); // 4.提交任务给执行器执行 executor.execute(futureTask); // 5.获取任务的执行结果 String result = futureTask.get(3, TimeUnit.SECONDS); System.out.println("任务执行结果:" + result); // 6.关闭线程池(可选) executor.shutdown(); } }

输出结果同上!

如果想尝试取消任务的执行,也可以通过如下方式来实现!

boolean isSuccess = futureTask.cancel(true); System.out.println("任务是否取消成功:" + isSuccess);

除此之外,如果仔细的分析Future接口的类关系,会发现它的实现类非常的多,FutureTask只是它的一个基础实现类而已,部分类关系图如下!

其它常用实现类简介:

  • CompletableFuture:支持传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法

  • ForkJoinTask:支持把一个大任务拆成多个小任务,然后并行执行,在多核 CPU 上可以显著提升程序的执行效率

  • ScheduledFuture:支持周期性定时的执行任务,其中ScheduledFutureTask是一个私有类,只能通过ScheduledThreadPoolExecutor初始化操作

关于CompletableFutureForkJoinTaskScheduledFuture,我们会在后面的文章中,再次单独介绍具体的用法。

三、小结

本文主要围绕Future接口用法做了一次简单的知识总结,其中FutureTask类是Future接口中一个非常重要的实现类,通过它可以获取异步任务执行的返回值,通常用于异步计算带有返回值的任务。

限于篇幅的原因,本文没有对FutureTask做过深入的原理讲解,主要围绕具体用法进行介绍,有兴趣的朋友可以阅读这篇文章《Java的Future机制详解》,以便更清晰的了解它的实现原理。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 12:28:57

提升多模态推理效率|Qwen3-VL-WEBUI镜像全面解析

提升多模态推理效率&#xff5c;Qwen3-VL-WEBUI镜像全面解析 随着多模态大模型在视觉理解、图文生成和跨模态推理等场景的广泛应用&#xff0c;如何高效部署具备强大能力的视觉语言模型&#xff08;VLM&#xff09;成为开发者关注的核心问题。阿里云推出的 Qwen3-VL-WEBUI 镜像…

作者头像 李华
网站建设 2026/4/16 12:22:55

单目3D感知教程:MiDaS模型后处理优化方法

单目3D感知教程&#xff1a;MiDaS模型后处理优化方法 1. 引言&#xff1a;从2D图像到3D空间理解 1.1 AI 单目深度估计 - MiDaS 在计算机视觉领域&#xff0c;如何让AI“看懂”三维世界一直是核心挑战之一。传统方法依赖双目立体视觉或多传感器融合&#xff08;如LiDAR&#…

作者头像 李华
网站建设 2026/4/16 10:19:24

ResNet18避坑大全:云端GPU按需使用,不花冤枉钱

ResNet18避坑大全&#xff1a;云端GPU按需使用&#xff0c;不花冤枉钱 1. 为什么选择ResNet18&#xff1f; ResNet18是深度学习领域最经典的图像分类模型之一&#xff0c;特别适合中小型数据集和快速验证场景。它就像摄影界的"傻瓜相机"——操作简单但效果可靠&…

作者头像 李华
网站建设 2026/4/16 12:58:41

多模态AI效率革命|基于Qwen3-VL-WEBUI构建智能办公助手

多模态AI效率革命&#xff5c;基于Qwen3-VL-WEBUI构建智能办公助手 在数字化办公日益普及的今天&#xff0c;传统“输入-输出”模式的人机交互已难以满足复杂、动态的工作场景。用户不再满足于让AI“看懂图片”或“写一段话”&#xff0c;而是期望它能真正理解上下文、执行任务…

作者头像 李华
网站建设 2026/3/31 8:42:56

Qwen3-VL-WEBUI部署实践|基于阿里开源视觉语言模型快速搭建交互界面

Qwen3-VL-WEBUI部署实践&#xff5c;基于阿里开源视觉语言模型快速搭建交互界面 随着多模态大模型在图像理解、视频分析和跨模态推理等领域的广泛应用&#xff0c;Qwen3-VL 作为通义千问系列中最新一代的视觉语言模型&#xff0c;凭借其强大的图文融合能力与增强的空间感知机制…

作者头像 李华
网站建设 2026/4/16 8:50:24

2026企业档案管理系统选型攻略:核心指标+避坑要点

在数字经济深度渗透的2026年&#xff0c;企业档案已从传统“纸质存根”升级为核心信息资产&#xff0c;档案管理系统也成为保障合规运营、提升协作效率的关键基础设施。然而&#xff0c;市场上系统产品琳琅满目&#xff0c;选型失误不仅会造成成本浪费&#xff0c;更可能埋下数…

作者头像 李华