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.mzph.cn/news/666637.shtml

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

相关文章

【Linux系统 02】Shell脚本

目录 一、Shell概述 二、输入输出 三、分支控制 1. 表达式 2. if 分支 3. case 分支 四、循环控制 1. for 循环 2. while 循环 3. select 循环 五、函数 一、Shell概述 Shell是Linux系统连接用户和操作系统的外壳程序&#xff0c;将用户的输入和请求选择性传递给操…

Java中Object类常用的12个方法

前言 Java 中的 Object 方法在面试中是一个非常高频的点&#xff0c;毕竟 Object 是所有类的“老祖宗”。Java 中所有的类都有一个共同的祖先 Object 类&#xff0c;子类都会继承所有 Object 类中的 public 方法。 先看下 Object 的类结构&#xff1a; 1. getClass 方法 pub…

「悬浮捷径SoftCircle」安卓平台的hao123,一键打开万物

罗老师的onestep一步发布之前, 终端的打开形式还拘泥于桌面和负一屏 这种方式够简洁,但缺点明显: 1.入口单一性:只能在app首页和各种扫一扫之间选择和切换 2.操作复杂:入口切换需要频繁的进入退出桌面,步骤过于繁杂 以下是悬浮捷径SoftCircle的解决方式 1.入口的丰富性: 安卓平…

如何在飞凌嵌入式T113-i开发板的Buildroot中移植MQTT协议?

在实际的项目开发中&#xff0c;工程师朋友们可能会需要在文件系统中移植一些工具或协议&#xff0c;那么该如何进行移植操作呢&#xff1f; 我们可以通过添加package包配置的方式在OK113i-S开发板的Buildroot中移植新功能。本篇文章&#xff0c;小编就以在Buildroot移植MQTT协…

关于Django部署

首先了解一下开发环境服务器跟生产环境服务器有何不同。 一、我们通过 python manage.py runserver 启动开发环境服务器&#xff0c;这条命令背后做了哪些事情&#xff1f; 1、首先加载Django项目的设置&#xff08;settings&#xff09; 2、检查数据库迁移&#xff0c;确保数…

Leetcode92:反转链表II(区间反转链表)

一、题目 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#xff1a…

Multisim14.0仿真(五十一)基于LM555定时器的分频器设计

一、1KHz脉冲设置&#xff1a; 二、555脉冲电路&#xff1a; 三、仿真电路&#xff1a; 四、运行仿真&#xff1a;

Day 1. 学习linux高级编程之Shell命令和IO

1.C语言基础 现阶段学习安排 2.IO编程 多任务编程&#xff08;进程、线程&#xff09; 网络编程 数据库编程 3.数据结构 linux软件编程 1.linux&#xff1a; 操作系统&#xff1a;linux其实是操作系统的内核 系统调用&#xff1a;linux内核的函数接口 操作流程&#xff…

Unity类银河恶魔城学习记录1-10 PlayerWallJump源代码 P37

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Player.cs using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; u…

海外YouTube视频点赞刷单悬赏任务投资理财源码/tiktok国际版刷单理财

测试环境&#xff1a;Linux系统CentOS7.6、宝塔、PHP7.3、MySQL5.7&#xff0c;根目录public&#xff0c;伪静态Laravel5&#xff0c;开启SSL证书 前端&#xff1a;修改网站的默认文档 index.html 为第一个&#xff0c; index.php 改成第二个 &#xff0c;或者前端访问 index.…

OJ_整数奇偶排序

题干 c实现 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<algorithm> using namespace std;//compare函数不交换返回true bool compare(int a, int b) {//1.a奇数&#xff0c;b偶数&#xff0c;不交换//2.a奇数&#xff0c;b奇数&#xff0c;a比b…

C语言实现跳表(附源码)

最近在刷一些链表的题目&#xff0c;在leetcode上有一道设计跳表的题目&#xff0c;也是通过查阅各种资料&#xff0c;自己实现出来&#xff0c;感觉这是种很神奇的数据结构。 一.简介 跳表与红黑树&#xff0c;AVL树等&#xff0c;都是一种有序集合&#xff0c;那既然是有序…

Prompt Engneering(提示词工程)

大模型的目标是理解和生成人类语言。给定一些词语&#xff0c;语言模型可以预测下一个词语可能是什么&#xff0c;或者给定的一些词语生层对应内容。 那么如何引导它们产生期望的输出&#xff0c;或者说如何提问&#xff0c;就成为了一个关键的问题。这就引入了一个重要的概念…

QStandardItemModel与QTableView里如何设置复选框居中

笔者为这个问题思索了不少时间&#xff0c;这个问题就是c qt里创建了一个QStandardItemModel设置了表格的表头&#xff0c;往表格填充数据时&#xff0c;数据的复选框左对齐&#xff0c;想要设置复选框居中对齐&#xff0c;不知道如何处理&#xff0c;这里给出代码与运行效果&a…

用Python画一条祥龙,祝您新年龙腾万里

用Python画一条祥龙&#xff0c;祝您新年龙腾万里 龙年到了&#xff0c;祝大家新年龙行龘龘&#xff0c;龙腾万里&#xff01; 从2021年开始&#xff0c;我每年都用Python画一幅当年生肖的图。 用Python标准库turtle画一头金牛&#xff0c;祝您新年牛气冲天&#xff01; 用P…

vscode 括号 python函数括号补全

解决方法 在setting.json中添加 “python.analysis.completeFunctionParens”: true 打开设置&#xff1b; 点击图中按钮打开setting.json文件 添加 “python.analysis.completeFunctionParens”: true

apipost 简单的性能压测总结

1、简单的使用机型牌评估 1&#xff09;jdk默认256M给100用&#xff0c;推荐给1000人同时用JVM 堆栈建议2G~4G&#xff08;目前定了机型4核8G内存 2T磁盘做radio0存储&#xff09;&#xff1b; 2&#xff09;数据库配置文件写了占了2G内存&#xff08;my.cnf文件&#xff09…

Python算法100例-1.3 牛顿迭代法求方程根

完整源代码项目地址&#xff0c;关注博主私信’源代码’后可获取 1&#xff0e;问题描述 编写用牛顿迭代法求方程根的函数。方程为 a x 3 b x 2 c x d 0 ax^3bx^2cxd0 ax3bx2cxd0&#xff0c;系数a、b、c、d由主函数输入&#xff0c;求x在1附近的一个实根。求出根后&…

详解SkyWalking前端监控的性能指标

SkyWalking 从8.2.0版本开始支持对前端浏览器端的性能进行监控&#xff0c;不仅可以像以前一样监控浏览器发送给后端服务的与请求&#xff0c;还能看到前端的渲染速度、错误日志等信息——这些信息是获取最终用户体验的最有效指标。实现的方式是引入skywalking-client-js库&…

STL篇三:list

文章目录 前言1.list的介绍和使用1.1 list的介绍1.2 list的使用1.3 list的迭代器的失效 2.list的模拟实现2.1 结点的封装2.2 迭代器的封装2.2.1 正向迭代器2.2.2 反向迭代器 2.3 list功能的实现2.3.1 迭代器的实例化及begin()、end() 2.3.2 构造函数2.3.3 赋值运算符重载2.3.4 …