Java并发基础:FutureTask全面解析!

Java并发基础:FutureTask全面解析! - 程序员古德

内容概要

FutureTask结合了FutureRunnable接口,它能够异步执行任务,提高程序响应性,可以获取任务执行结果,并且支持任务取消机制,提高了灵活性,同时,它简化了并发编程,使多线程开发更加便捷。

核心概念

FutureTask主要用来解决异步计算的问题,它提供了一种便捷的方式,可以将耗时的计算任务提交给另一个线程去执行,而当前线程可以继续执行其他任务,从而实现并发执行的效果,它实现了FutureRunnable接口,因此它既可以作为Runnable被线程执行,又可以作为Future得到计算结果,当把FutureTask提交给ExecutorService执行后,它会返回一个表示异步计算结果的Future对象,这个Future对象检查计算是否完成,并获取计算的结果。

FutureTask主要用来解决以下问题:

  1. 异步执行:当有一个耗时的计算任务,并且不想阻塞当前线程的执行时,可以使用FutureTask将任务提交给另一个线程去执行,这样,当前线程可以继续执行其他任务,提高了整体的执行效率。
  2. 获取计算结果FutureTask提供了检查计算是否完成,并获取计算结果的方法,可以使用Future.get()方法来获取计算结果,如果计算还没有完成,这个方法会阻塞,直到计算完成为止。这使得可以在需要的时候方便地获取异步计算的结果。
  3. 异常处理:如果异步计算抛出了异常,那么调用Future.get()方法时会抛出ExecutionException,这样,可以在获取计算结果的同时,方便地处理异步计算中可能出现的异常。
  4. 任务取消:通过Future.cancel()方法,可以取消还没有开始的或者正在进行的异步计算,这为提供了更多的灵活性,可以根据需要动态地控制异步计算的执行。

代码案例

import java.util.concurrent.*;  // 定义一个Callable任务,它实现了call()方法,该方法有返回值  
class MyCallableTask implements Callable<Integer> {  private int num;  public MyCallableTask(int num) {  this.num = num;  }  @Override  public Integer call() throws Exception {  // 模拟耗时操作,比如计算一个数的平方  int result = num * num;  System.out.println("计算完成: " + result);  return result;  }  
}  public class FutureTaskDemo {  public static void main(String[] args) {  // 创建一个ExecutorService,用于执行异步任务  ExecutorService executor = Executors.newSingleThreadExecutor();  // 创建一个Callable任务实例  Callable<Integer> callableTask = new MyCallableTask(5);  // 使用FutureTask包装Callable任务  FutureTask<Integer> futureTask = new FutureTask<>(callableTask);  // 提交FutureTask到ExecutorService中执行,但是这里有个问题:  // executor.submit(futureTask); // 这行代码实际上是错误的,因为futureTask已经被明确指定了任务  // 正确的做法是直接提交Callable任务给ExecutorService,并获得Future引用  Future<Integer> future = executor.submit(callableTask);  // 在这里可以做其他事情,而Callable任务在另一个线程中异步执行  try {  // 获取异步计算的结果,如果计算还没完成,get()方法会阻塞  Integer result = future.get(); // 注意这里使用的是future,而不是futureTask  System.out.println("获取到的结果是: " + result);  } catch (InterruptedException | ExecutionException e) {  // 处理可能的异常  e.printStackTrace();  } finally {  // 关闭ExecutorService  executor.shutdown();  }  }  
}

在上述代码中:

  1. MyCallableTask类实现了Callable接口,并覆盖了call()方法,该方法计算一个数的平方并返回结果。
  2. FutureTaskDemo类的main方法中,创建一个ExecutorService实例,用于执行异步任务。
  3. 然后,创建一个Callable任务实例,并使用FutureTask将其包装起来,将FutureTask提交到ExecutorService中执行。
  4. 最后,通过调用futureTask.get()方法来获取异步计算的结果,如果计算还没完成,get()方法会阻塞,直到结果可用为止。

代码输出如下结果:

计算完成: 25  
获取到的结果是: 25

核心API

FutureTask 它实现了 FutureRunnable 接口,因此既可以作为异步计算的结果,也可以作为 Runnable 被执行,FutureTask 通常用于那些需要计算结果的异步计算场景,下面是 FutureTask 中一些重要方法的简要说明:

  1. FutureTask(Callable<V> callable) 构造函数
    • 创建一个 FutureTask,该任务将调用给定的 Callable 对象来计算其结果。
  2. void run()
    • 开始执行计算任务,这个方法通常在另一个线程中调用,例如在通过 Thread 类或者 Executor 框架提交任务时。
  3. V get()
    • 获取计算结果,如果计算还没有完成,这个方法会阻塞直到计算完成。
  4. V get(long timeout, TimeUnit unit)
    • 尝试在给定的时间内获取计算结果,如果计算在这段时间内完成,返回结果;否则,抛出 TimeoutException
  5. boolean isDone()
    • 检查计算是否已经完成,如果完成,返回 true;否则,返回 false
  6. boolean isCancelled()
    • 检查任务是否被取消,如果任务在开始前被取消,或者在执行过程中被中断并且还没有完成,那么这个方法返回 true
  7. boolean cancel(boolean mayInterruptIfRunning)
    • 尝试取消任务的执行,如果任务还没有开始,或者如果 mayInterruptIfRunningtrue 并且任务正在运行,那么这个方法会尝试中断正在执行任务的线程。如果任务被成功取消,返回 true;否则,返回 false

核心总结

FutureTask允许将耗时的任务放到后台异步执行,不阻塞主线程,提升系统响应性,当任务完成后,可以方便地获取计算结果,无需额外的同步措施,它还提供了取消机制,能够中途终止任务的执行。但是使用FutureTask时需要注意,它的get方法只能调用一次以获取结果,重复调用会抛出异常,如果异步任务中抛出异常,只有在调用get方法时才会抛出ExecutionException,异常处理的时机与位置可能不那么直观。

个人思考

Java并发基础:Phaser全面解析! - 程序员古德

RunnableFuture和Future有什么区别?

在Java中,Future接口和RunnableFuture接口都是与并发编程相关的接口,它们用于处理异步计算的结果,但是他们在使用场景上有这明显的接区别,如下:

  1. Future接口:

    • Future接口表示异步计算的结果,它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。
    • Future.get()方法用于获取计算的结果。如果计算还没有完成,这个方法会阻塞直到计算完成。
    • Future.isDone()方法用于检查计算是否已经完成。
    • Future.cancel()方法用于取消计算,如果计算还没有开始,那么这个计算将不会进行,如果计算已经在进行,那么这个方法可能无法停止计算,具体取决于具体的实现和计算能力。
    • Future接口不能直接运行,它只是一个表示可能还没有完成的异步计算的结果的占位符,要运行任务并获取Future对象,通常需要将任务提交给ExecutorService
  2. RunnableFuture接口:

    • RunnableFuture接口扩展了RunnableFuture接口,这意味着它既可以作为Runnable被线程执行,又可以作为Future来获取执行结果。
    • RunnableFuture.run()方法是Runnable接口的一部分,用于执行异步计算。
    • Future接口一样,RunnableFuture也提供了get()isDone()cancel()等方法来检查计算的状态,获取结果或取消计算。
    • Future不同的是,RunnableFuture可以被直接执行,这意味着可以创建一个RunnableFuture的实现,将其传递给一个线程来执行,而不必通过ExecutorService
  3. 核心区别

    • RunnableFutureFuture的一个扩展,它添加了Runnable接口的功能,因此可以被直接执行,这使得RunnableFuture更加灵活,因为它既可以被线程直接执行,又可以作为Future来管理和获取结果。

    • 通常,不会直接使用RunnableFuture,而是使用FutureTask这个RunnableFuture的实现类,FutureTask允许将CallableRunnable任务封装为一个可以被线程执行的对象,并且可以通过Future接口获取任务的结果。

关注我,每天学习互联网编程技术 - 程序员古德

END!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/452053.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入学习《大学计算机》系列之第1章 1.6节——你真的了解计算机存储器吗

一.欢迎来到我的酒馆 第1章 1.6节&#xff0c;你真的了解计算机存储器吗。 目录 一.欢迎来到我的酒馆二.计算机存储器2.1 计算机存储器简介2.2 计算机存储器发展史2.3 计算机存储器发展史总结 三.计算机存储器分类3.1 主存储器3.2 内存3.3 缓存3.4 寄存器3.5 二级存储器3.6 存…

【C/C++ 11】贪吃蛇游戏

一、题目 贪吃蛇游戏机制是通过控制蛇上下左右移动并吃到食物得分。 蛇头碰到墙壁或者碰到蛇身就游戏结束。 食物随机生成&#xff0c;蛇吃到食物之后蛇身变长&#xff0c;蛇速加快。 二、算法 1. 初始化游戏地图并打印&#xff0c;地图的边缘是墙&#xff0c;地图的每个坐…

计算机毕业设计 基于SpringBoot的宠物爱心组织管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

【双周赛】第123场双周赛

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 力扣每日一题_ 【1】三角形类型Ⅱ 100222. 三角形类型 IIhttps://leetcode.cn/problems/type-of-triangle-ii/ 简单题&#xff0c;直接过了 cl…

高级Java开发工程师岗位的基本职责(合集)

高级Java开发工程师岗位的基本职责1 职责&#xff1a; 1、负责区块链产品的研发&#xff0c;独立或与团队合作&#xff0c;按时保质完成软件开发项目; 2、参与产品系统设计、概要设计工作&#xff0c;核心功能的代码编写; 3、独立解决和指导其他同事处理开发中遇到的难点问题; …

智能决策的艺术:探索商业分析的最佳工具和方法

文章目录 一、引言二、商业分析思维概述三、数据分析在商业实践中的应用四、如何培养商业分析思维与实践能力五、结论《商业分析思维与实践&#xff1a;用数据分析解决商业问题》亮点内容简介作者简介目录获取方式 一、引言 随着大数据时代的来临&#xff0c;商业分析思维与实…

MagicVideo-V2:多阶段高保真视频生成框架

本项工作介绍了MagicVideo-V2&#xff0c;将文本到图像模型、视频运动生成器、参考图像embedding模块和帧内插模块集成到端到端的视频生成流程中。由于这些架构设计的好处&#xff0c;MagicVideo-V2能够生成具有极高保真度和流畅度的美观高分辨率视频。通过大规模用户评估&…

【AG32VF407】国产MCU+FPGA Verilog双边沿检测输出方波

视频讲解 [AG32VF407]国产MCUFPGA Verilog双边沿检测输出方波 实验过程 本次使用使用AG32VF407开发板中的FPGA&#xff0c;使用双clk的双边沿进行检测&#xff0c;同步输出方波 同时可以根据输出的方波检测clk的频率&#xff0c;以及双clk的相位关系&#xff0c;如下为verilog…

#从零开始# 在深度学习环境中,如何用 pycharm配置使用 pipenv 虚拟环境

为Python项目创建虚拟环境 在深度学习环境和一般python环境中安装pipenv基本一致&#xff0c;只需要确认好pipenv指定的python版本即可,安装pipenv前&#xff0c;可以通过python --version来确认安装版本 快捷键&#xff1a;crtl alt S 查看interpreter&#xff0c;查看所有…

MySQL知识点总结(三)——事务

MySQL知识点总结&#xff08;三&#xff09;——事务 事务事务的四大特性ACID原子性一致性隔离性持久性 脏读、幻读、不可重复读脏读不可重复读幻读 隔离级别读未提交读已提交可重复读串行化 事务的原理InnoDB如何实现事务的ACID事务的两阶段提交redo log与binlog的区别事务两阶…

k8s学习-Kubernetes的包管理器Helm

1.1 为何需要Helm Kubernetes能够很好地组织和编排容器&#xff0c;但它缺少⼀个更高层次的应用打包工具&#xff0c;而Helm就是来干这件事的。 先来看个例子。 比如对于⼀个MySQL服务&#xff0c;Kubernetes需要部署下面这些对象&#xff1a; &#xff08;1&#xff09;Serv…

【消息队列】kafka整理

kafka整理 整理kafka基本知识供回顾。