FutureTask详解

2023-10-27

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。

FutureTask介绍

一个可取消的异步计算。FutureTask提供了对Future的基本实现,可以调用方法去开始和取消一个计算,可以查询计算是否完成并且获取计算结果。只有当计算完成时才能获取到计算结果,一旦计算完成,计算将不能被重启或者被取消,除非调用runAndReset方法。
除了实现了Future接口以外,FutureTask还实现了Runnable接口,因此FutureTask交由Executor执行,也可以直接用线程调用执行(futureTask.run())。根据FutureTask的run方法执行的时机,FutureTask可以处于以下三种执行状态:
1、未启动:在FutureTask.run()还没执行之前,FutureTask处于未启动状态。当创建一个FutureTask对象,并且run()方法未执行之前,FutureTask处于未启动状态。
2、已启动:FutureTask对象的run方法启动并执行的过程中,FutureTask处于已启动状态。
3、已完成:FutureTask正常执行结束,或者FutureTask执行被取消(FutureTask对象cancel方法),或者FutureTask对象run方法执行抛出异常而导致中断而结束,FutureTask都处于已完成状态。
FutureTask状态迁移图
在这里插入图片描述当FutureTask处于未启动或者已启动的状态时,调用FutureTask对象的get方法会将导致调用线程阻塞。当FutureTask处于已完成的状态时,调用FutureTask的get方法会立即放回调用结果或者抛出异常。
当FutureTask处于未启动状态时,调用FutureTask对象的cancel方法将导致线程永远不会被执行;当FutureTask处于已启动状态时,调用FutureTask对象cancel(true)方法将以中断执行此任务的线程的方式来试图停止此任务;当FutureTask处于已启动状态时,调用FutureTask对象cancel(false)方法将不会对正在进行的任务产生任何影响;当FutureTask处于已完成状态时,调用FutureTask对象cancel方法将返回false;
FutureTask的get和cancel的执行示意图
在这里插入图片描述

FutureTask使用

可以把FutureTask交给Executor执行;也可以通ExecutorService.submit(…)方法返回一个FutureTask,然后执行FutureTask.get()方法或FutureTask.cancel(…)方法。除此以外,还可以单独使用FutureTask。
当一个线程需要等待另一个线程把某个任务执行完后它才能继续执行,此时可以使用FutureTask。假设有多个线程执行若干任务,每个任务最多只能被执行一次。当多个线程试图同时执行同一个任务时,只允许一个线程执行任务,其他线程需要等待这个任务执行完后才能继续执行。下面是对应的示例代码。

private final ConcurrentMap<Object, Future<String>> taskCache = new ConcurrentHashMap<>();

    private String executionTask(final String taskName)throws ExecutionException, InterruptedException {
        while (true) {
            Future<String> future = taskCache.get(taskName); // 1.1,2.1
            if (future == null) {
                Callable<String> task = () -> taskName;
                FutureTask<String> futureTask = new FutureTask<>(task);
                future = taskCache.putIfAbsent(taskName, futureTask); // 1.3
                if (future == null) {
                    future = futureTask;
                    futureTask.run(); // 1.4执行任务
                }
            }
            try {
                return future.get(); // 1.5,
            } catch (CancellationException e) {
                taskCache.remove(taskName, future);
            }
        }
    }

在这里插入图片描述当两个线程试图同时执行同一个任务时,如果Thread 1执行1.3后Thread 2执行2.1,那么接下来Thread 2将在2.2等待,直到Thread 1执行完1.4后Thread 2才能从2.2(FutureTask.get())返回

FutureTask实现

jdk1.8的FutureTask有个说明:
修订说明:这与这个类以前依赖AbstractQueuedsynchronizer的版本不同,主要是为了避免在取消竞争期间保留中断状态让用户感到意外。在当前的设计中,Sync控件依赖于通过CAS更新的“state”字段来跟踪完成,以及一个简单的Treiber堆栈来保存等待的线程。
风格注意:与往常一样,我们绕过了使用 AtomicXFieldUpdaters的开销,而是直接使用Unsafe。

Future

FutureTask实现了Future接口,Future接口有5个方法:
1、boolean cancel(boolean mayInterruptIfRunning)
尝试取消当前任务的执行。如果任务已经取消、已经完成或者其他原因不能取消,尝试将失败。如果任务还没有启动就调用了cancel(true),任务将永远不会被执行。如果任务已经启动,参数mayInterruptIfRunning将决定任务是否应该中断执行该任务的线程,以尝试中断该任务。
如果任务不能被取消,通常是因为它已经正常完成,此时返回false,否则返回true
2、boolean isCancelled()
如果任务在正常结束之前被被取消返回true
3、boolean isDone()
正常结束、异常或者被取消导致任务完成,将返回true
4、V get()
等待任务结束,然后获取结果,如果任务在等待过程中被终端将抛出InterruptedException,如果任务被取消将抛出CancellationException,如果任务中执行过程中发生异常将抛出ExecutionException。
5、V get(long timeout, TimeUnit unit)
任务最多在给定时间内完成并返回结果,如果没有在给定时间内完成任务将抛出TimeoutException。

FutureTask状态转换

FutureTask有以下7中状态:
在这里插入图片描述
FutureTask任务的运行状态,最初为NEW。运行状态仅在set、setException和cancel方法中转换为终端状态。在完成过程中,状态可能呈现出瞬时值INTERRUPTING(仅在中断运行程序以满足cancel(true)的情况下)或者COMPLETING(在设置结果时)状态时。从这些中间状态到最终状态的转换使用成本更低的有序/延迟写,因为值是统一的,需要进一步修改。
state:表示当前任务的运行状态,FutureTask的所有方法都是围绕state开展的,state声明为volatile,保证了state的可见性,当对state进行修改时所有的线程都会看到。
NEW:表示一个新的任务,初始状态
COMPLETING:当任务被设置结果时,处于COMPLETING状态,这是一个中间状态。
NORMAL:表示任务正常结束。
EXCEPTIONAL:表示任务因异常而结束
CANCELLED:任务还未执行之前就调用了cancel(true)方法,任务处于CANCELLED
INTERRUPTING:当任务调用cancel(true)中断程序时,任务处于INTERRUPTING状态,这是一个中间状态。
INTERRUPTED:任务调用cancel(true)中断程序时会调用interrupt()方法中断线程运行,任务状态由INTERRUPTING转变为INTERRUPTED

可能的状态过渡:
 1、NEW -> COMPLETING -> NORMAL:正常结束
 2、NEW -> COMPLETING -> EXCEPTIONAL:异常结束
 3、NEW -> CANCELLED:任务被取消
 4、NEW -> INTERRUPTING -> INTERRUPTED:任务出现中断
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FutureTask详解 的相关文章

  • keepalived-lvs-nat-主备模型实现高可用负载均衡

    keepalived简介 Keepalived的作用是检测web服务器的状态 如果有一台web服务器死机 或工作出现故障 Keepalived将检测到 并将有故障的web服务器从系统中剔除 当web服务器工作正常后Keepalived自动将

随机推荐

  • 移远公司 NB-IoT模块AT指令详细解释

    AT指令的分类和格式 AT指令分测试指令 读取参数指令 设置参数指令 执行命令指令四类 参见下表 命令 命令名称 命令功能 AT lt CMD gt 测试命令 询问模块支持哪些设置参数或者是那些项目 AT lt CMD gt 读取命令 读取
  • 2.数据定义语言DDL

    一 数据库定义语言 DDL Data Definition Language 是用于描述数据库中要存储的现实世界实体的语言 主要由create 添加 alter 修改 drop 删除 和 truncate 删除 四个关键字完成 二 crea
  • 服务器的软件架构

    1 服务器的整体架构 x86 2 服务器的软件整体架构 x86 3 服务器的软件介绍BIOS POST CPU 内存 外设初始化与资源分配 BIOS Setup 英文 中文 CPU Performance SATA等接口控制 BIOS BM
  • JS Date日期的使用

    Date 分两大系列 1 get系列 及获取时间 2 set系列 及设置时间 1 get系列的方法 1 getDate 返回一月中的某一天 2 getDay 返回一周中的某一天 0 6 0代表周日 6代表周一 3 getFullyear 返
  • 架构师分享 7 种软件设计架构 (文末送书)

    文末留言送书5本 架构模式是对给定上下文的软件架构中常见问题的一种通用的可复用的解决方案 一种模式就是特定上下文的问题的一种解决方案 然而 很多开发者至今还对各种软件架构模式之间的差别搞不清 甚至对其所知甚少 大体上 主要有下面这7种架构模
  • Haskell学习——语法

    if then else Haskell是以表达式为主导的语言 expression oriented 所有语句必须要能给出一个具体的值 比如我们喜闻乐见的if else结构 Prelude gt if True then 1
  • 《数值分析》-- 高斯求积公式

    文章目录 概述 一 高斯型求积公式的一般理论 1 1 高斯型求积公式和高斯点 1 2 高斯点的特征 二 常用的高斯求积公式 2 1 高斯 勒让德求积公式 Gauss Legendre 2 2 高斯 切比雪夫求积公式 Gauss Chebys
  • 让生产力加倍的ChatGPT快捷指令

    我的新书 Android App开发入门与实战 已于2020年8月由人民邮电出版社出版 欢迎购买 点击进入详情 Why use ChatGPT Shortcut 简化流程 ChatGPT Shortcut 提供了快捷指令表 可以快速筛选和搜
  • OpenGL视频资料(LearnOpenGL中文)经典教材讲解

    OpenGL视频资料 LearnOpenGL中文 经典教材讲解 1 是中文 台湾的傅老师 讲的非常好 而且还是免费的 感谢傅老师的分享 视频地址 2 视频目录 讲解的非常仔细 可以说是手把手教 而且是openGL经典入门教材LearnOpe
  • [Python] Python基础入门笔记

    本篇是B站Python基础视频 有C Java编程基础容易理解 120分钟入门Python的学习笔记 Python基础笔记 一 Python 简介 1 Python执行过程 2 执行模式 二 语法规则 三 函数 1 内置函数 range 2
  • java基础练习—逢七游戏、不死神兔、百钱百鸡、利滚利

    1 逢七游戏 逢七过 规则是 从任意一个数字开始报数 当你要报的数字包含7或者是7 的倍数时都要说 过 为了帮助大家更好的玩这个游戏 这里我们直接在控制台打印出1 100之间的满足逢七必过 规则的数据 package com bdit pu
  • ThinkCentre进入BIOS,设置intel virtualization technology

    VMware安装提示cpu虚拟化intel virtualization technology ThinkCentre重启长按F1 按enter 开启intel virtualization technology F10保存即可 转载于 h
  • git团队开发使用流程概述和注意点

    重新温习了一下git 这篇文章主要总结一下使用git做开发的整体流程 所以不会做过多的git指令的详细说明 整体流程 这里我在本地进行模拟 我希望模拟达到的效果是 一共有4个端 project是一个仓库 manager是项目负责人 zs和l
  • 【面试】Java 必知必会

    必知必会 1 面向对象可以解释下么 都有哪些特性 关于封装 关于继承 重写 Override 关于多态 重载 如果只有方法返回值不同 可以构成重载吗 在 Java 中 什么时候使用重载 什么时候使用重写 子类对象作为父类对象使用 向上转型
  • 【Antlr】识别常见的词法结构

    1 概述 语法分析器通过输入的词法符号流来识别特定的语言结构 词法分析器通过输入的字符流来识别特定的语言结构 词法规则以大写字母开头 文法规则以小写字母开头 例如 ID是一个词法规则名 而expr是一 个文法规则名 2 配置标识符 在语法的
  • 数据结构—顺序表的初始化与销毁(C语言详细解读版1/3)

    顺序表 顺序表 SqList Sequence List 即顺序线性表 顺序表是在计算机内存中以数组的形式保存的线性表 是指用一组地址连续的存储单元依次存储数据元素的线性结构 使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中
  • 自动售卖系统开发系列——人脸识别自动售卖机三代BrotherSharp

    大纲 售卖机三代BrotherSharp的简介 售卖机三代BrotherSharp的方案介绍 系统整体组成 软件平台 硬件平台 售卖机三代BrotherSharp的实现过程 功能实现论述 软件流程图 源码 售卖机三代BrotherSharp
  • ArcGIS Desktop 遇到严重的应用程序错误

    由于项目初验 忙了几个月 感觉忙得并不值 好久都没更新博客了 一 问题 在关闭ArcMap时 ArcGIS Desktop 遇到严重的应用程序错误 环境是Windows 10 新装的系统 以前出现这种问题 一般有两种情况 一是ArcGIS
  • Pycharm调试debug指导

    PyCharm的调试有两种显示模式 Debugger和Console Debugger处以列表形式 列出每个元素的内容 Console处与直接Run输出类似 Debugger模式 Step Over Step Into 区别 调试方式 快捷
  • FutureTask详解

    前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住分享一下给大家 点击跳转到网站 FutureTask介绍 一个可取消的异步计算 FutureTask提供了对Future的基本实现 可以调用方法去开始和取消一个计算 可以查询