**FutureTask应用源码分析**(一)

1.1 FutureTask介绍

FutureTask是一个可以取消异步任务的类。FutureTask对Future做的一个基本实现。可以调用方法区开始和取消一个任务。
一般是配合Callable去使用。
异步任务启动之后,可以获取一个绑定当前异步任务的FutureTask。
可以基于FutureTask的方法去取消任务,查看任务是否结果,以及获取任务的返回结果。
FutureTask内部的整体结构中,实现了RunnableFuture的接口,这个接口又继承了Runnable, Future这个两个接口。所以FutureTask也可以作为任务直接交给线程池去处理。

1.2 FutureTask应用

大方向是FutureTask对任务的控制:

● 任务执行过程中状态的控制
● 任务执行完毕后,返回结果的获取

FutureTask的任务在执行run方法后,是无法被再次运行,需要使用runAndReset方法才可以。

public static void main(String[] args) throws InterruptedException {
// 构建FutureTask,基于泛型执行返回结果类型
// 在有参构造中,声明Callable或者Runnable指定任务
FutureTask<String> futureTask = new FutureTask<>(() -> {
System.out.println("任务开始执行……");
Thread.sleep(2000);
System.out.println("任务执行完毕……");
return "OK!";
});
// 构建线程池
ExecutorService service = Executors.newFixedThreadPool(10);
// 线程池执行任务
service.execute(futureTask);// futureTask提供了run方法,一般不会自己去调用run方法,让线程池去执行任务,由线程池去执行run方法
// run方法在执行时,是有任务状态的。任务已经执行了,再次调用run方法无效的。
// 如果希望任务可以反复被执行,需要去调用runAndReset方法
// futureTask.run();
// 对返回结果的获取,类似阻塞队列的poll方法
// 如果在指定时间内,没有拿到方法的返回结果,直接扔TimeoutException
// try {
// String s = futureTask.get(3000, TimeUnit.MILLISECONDS);
// System.out.println("返回结果:" + s);
// } catch (Exception e) {
// System.out.println("异常返回:" + e.getMessage());
// e.printStackTrace();
// }
// 对返回结果的获取,类似阻塞队列的take方法,死等结果
// try {
// String s = futureTask.get();
// System.out.println("任务结果:" + s);
// } catch (ExecutionException e) {
// e.printStackTrace();
// }
// 对任务状态的控制
// System.out.println("任务结束了么?:" + futureTask.isDone());
// Thread.sleep(1000);
// System.out.println("任务结束了么?:" + futureTask.isDone());
// Thread.sleep(1000);
// System.out.println("任务结束了么?:" + futureTask.isDone());
}

1.3 FutureTask源码分析

看FutureTask的源码,要从几个方向去看:
● 先查看FutureTask中提供的一些状态
● 在查看任务的执行过程

1.3.1 FutureTask中的核心属性

清楚任务的流转流转状态是怎样的,其次对于核心属性要追到是干嘛的。

/**
FutureTask的核心属性
FutureTask任务的状态流转
* NEW -> COMPLETING -> NORMAL 任务正常执行,并且返回结果也正常返回
* NEW -> COMPLETING -> EXCEPTIONAL 任务正常执行,但是结果是异常
* NEW -> CANCELLED 任务被取消
* NEW -> INTERRUPTING -> INTERRUPTED 任务被中断
*/
// 记录任务的状态
private volatile int state;
// 任务被构建之后的初始状态
private static final int NEW = 0;
private static final int COMPLETING = 1;
private static final int NORMAL = 2;
private static final int EXCEPTIONAL = 3;
private static final int CANCELLED = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED = 6;
/** 需要执行任务,会被赋值到这个属性 */
private Callable<V> callable;
/** 任务的任务结果要存储在这几个属性中 */
private Object outcome; // non-volatile, protected by state reads/writes
/** 执行任务的线程 */
private volatile Thread runner;
/** 等待返回结果的线程Node对象, */
private volatile WaitNode waiters;
static final class WaitNode {
volatile Thread thread;
volatile WaitNode next;
WaitNode() { thread = Thread.currentThread(); }
}

1.3.2 FutureTask的run方法

任务执行前的一些判断,以及调用任务封装结果的方式,还有最后的一些后续处理

// 当线程池执行FutureTask任务时,会调用的方法
public void run() {
// 如果当前任务状态不是NEW,直接return告辞
if (state != NEW ||
// 如果状态正确是NEW,这边需要基于CAS将runner属性设置为当前线程
// 如果CAS失败,直接return告辞
!UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread()))
return;
try {
// 将要执行的任务拿到
Callable<V> c = callable;
// 健壮性判断,保证任务不是null
// 再次判断任务的状态是NEW(DCL)
if (c != null && state == NEW) {
// 执行任务
// result:任务的返回结果
// ran:如果为true,任务正常结束。 如果为false,任务异常结束。
V result;
boolean ran;
try {
// 执行任务
result = c.call();
// 正常结果,ran设置为true
ran = true;
} catch (Throwable ex) {
// 如果任务执行期间出了异常// 返回结果置位null
result = null;
// ran设置为false
ran = false;
// 封装异常结果
setException(ex);
}
if (ran)
// 封装正常结果
set(result);
}
} finally {
// 将执行任务的线程置位null
runner = null;
// 拿到任务的状态
int s = state;
// 如果状态大于等于INTERRUPTING
if (s >= INTERRUPTING)
// 进来代表任务中断,做一些后续处理
handlePossibleCancellationInterrupt(s);
}
}

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

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

相关文章

Windows11搭建Python环境(2)- Anaconda虚拟环境中安装Git

在搭建MetaGPT运行环境过程中&#xff0c;使用了Anaconda虚拟环境&#xff0c;在运行MetaGPT时出现错误&#xff1a; 可以看到是没有找到git指令。 在Windows上安装Git&#xff0c;可以直接去官网下载.exe文件&#xff0c;然后安装即可。 但是上面安装完成后&#xff0c;是无…

三方接口对接常见数据处理方式汇总

文章目录 数据请求格式application/json接收发送 multipart/form-data接收发送 application/x-www-form-urlencoded接收发送 text/xml接收发送 Request请求中各个数据载体获取方法HeaderParameterInputStreamAttribute 二次封装HttpServletRequest参考 验签与加密 日常开发中&a…

【mfc/VS2022】绘图工具设计-绘制基本图元1

基于&#xff1a;https://blog.csdn.net/weixin_51599044/article/details/111741111 实现的功能&#xff1a; 绘制图元的方法&#xff1a; 前5种图元的菜单项均在“绘制”菜单里。 1.直线:按下左键作为起点&#xff0c;按住左键拖动鼠标到你想设定的终点&#xff0c;然后放开…

使用Map.clear()、List.clear()方法,清空时注意!

对 Map、List 对象进行清空操作时&#xff0c;常常会使用 clear() 方法。 例如&#xff0c;清空 Map Map map new HashMap();map.put("key1","value1");map.put("key2","value2");System.out.println(map.size()); //2map.clear();Sy…

.gitignore文件设置了忽略但不生效,git提交过程解析

这里写目录标题 第一章、gitignore文件设置了忽略路径&#xff0c;但是不生效1.1&#xff09;原因1.2&#xff09;解决 第一章、gitignore文件设置了忽略路径&#xff0c;但是不生效 1.1&#xff09;原因 在初次提交代码的时候&#xff0c;没有进行文件忽略&#xff0c;某些文…

【Python_PySide6学习笔记(三十一)】基于PySide6实现自定义串口设备连接界面类:可实现串口连接断开、定时发送等功能

基于PySide6实现自定义串口设备连接界面类:可实现串口连接关闭、定时发送等功能 基于PySide6实现自定义串口设备连接界面类:可实现串口连接关闭、定时发送等功能前言一、界面布局二、串口相关功能实现三、完整代码四、调用方法五、实现效果基于PySide6实现自定义串口设备连接…

快慢指针-Floyd判圈算法

对于环形链表是否存在环的做法&#xff0c;普通算法可以通过额外Hash数组来存储链表元素&#xff0c;直到Hash数组中出现重复元素。时间复杂度O(n)&#xff0c;空间复杂度O(n) Floyd判圈算法通过利用快慢指针的移动来实现&#xff0c;时间复杂度O&#xff08;n&#xff09;&am…

hash 路由和 history 路由的区别

Hash 路由&#xff08;Hash Routing&#xff09;&#xff1a; URL 结构&#xff1a; 使用URL中的哈希部分&#xff08;#&#xff09;来表示不同的路由。例如&#xff0c;http://example.com/#/page1。实现方式&#xff1a; 前端路由器通过监听 window.onhashchange 来判断路由的…

Java进阶之旅第三天

Java进阶之旅第三天 文章目录 Java进阶之旅第三天TreeMap特点:题目 使用TreeMap进行数据统计题目: TreeMap 特点: 1.TreeMap根TreeSet底层原理一样,都是红黑树结构2.由键决定特性: 不重复,无索引,可排序3.可排序: 对键进行牌序注意: 默认按照键的从小到大进行排序,也可以自己…

【备战蓝桥杯】今天给大家整点解压的~

【备战蓝桥杯】今天给大家整点解压的~ 蓝桥杯备赛 | 洛谷做题打卡day8 文章目录 【备战蓝桥杯】今天给大家整点解压的~ 蓝桥杯备赛 | 洛谷做题打卡day8[NOIP2017 普及组] 成绩题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提…

【C语言编程之旅 1】刷题篇-初识c语言

文章目录 第一题答案及解析 第二题答案及解析 第三题答案及解析 第四题答案及解析 第五题答案及解析 第六题答案及解析 第一题 答案及解析 C语言中内置类型包括&#xff1a; char //字符数据类型 short //短整型 int //整形 long //长整型 long long //更长的整形 float //单精…

ArcGIS Pro 拓扑编辑和常见一些拓扑错误处理

7.4 拓扑编辑 拓扑编辑也叫共享编辑&#xff0c;多个数据修改时&#xff0c;一块修改&#xff0c;如使用数据&#xff1a;chp7\拓扑检查.gdb,数据集DS下JZX、JZD和DK&#xff0c;加载地图框中&#xff0c;在“地图”选项卡下选择“地图拓扑”或“ds_Topology(地理数据库)”&…

Oracle-java下载、开源/商业许可证(收费、免费说明)、版本发布日志

Oracle-java下载、开源/商业许可证&#xff08;收费、免费说明&#xff09;、版本发布日志 下载开源/商业许可证&#xff08;收费、免费说明&#xff09;java8版本发布日志以上是一般情况&#xff0c;具体的以官网发布信息为准 下载 下载地址&#xff1a;https://www.oracle.c…

google cloud storage批量文件下载

背景&#xff1a; 一些google cloud storage文件的下载是需要付费的&#xff0c;一些是不需要的&#xff0c;不需要的直接点击下方的下载按钮即可&#xff0c;但是常常存在大量的文件下载&#xff0c;挨个下载有点费时间而且占内存&#xff0c;所以我尝试了批量下载到HPC&…

前端面试题-webpack

1.webpack是什么&#xff1f; 模块打包工具&#xff0c;用于将前端资源&#xff0c;如JavaScript、css、图片等打包成可以在浏览器运行的静态资源。可以将多个模块打包成一个或多个bundle。 主要功能&#xff1a; 模块化&#xff1a;可以将多个模块打包成一个或多个bundle&…

day17 二叉树part04

110. 平衡二叉树 简单 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 class Solution {public boolean isBalanced(TreeNode root) {re…

(2023版)斯坦福CS231n学习笔记:DL与CV教程 (3) | 正则化与最优化

前言 &#x1f4da; 笔记专栏&#xff1a;斯坦福CS231N&#xff1a;面向视觉识别的卷积神经网络&#xff08;23&#xff09;&#x1f517; 课程链接&#xff1a;https://www.bilibili.com/video/BV1xV411R7i5&#x1f4bb; CS231n: 深度学习计算机视觉&#xff08;2017&#xf…

智能代码:生成式 AI 在软件开发中的革命性角色

想象一下&#xff0c;在智能手机革命性地改变了我们的生活之后&#xff0c;现在轮到了生成式 AI 在软件开发领域掀起风暴。你知道吗&#xff0c;如果代码能自己编写自己&#xff0c;这将是多么惊人的一步&#xff1f;这就好比我们现在能轻松地用手机应用管理日常生活一样&#…

【嘉立创EDA-PCB设计指南】1.PCB基本概念及原理图绘制

前言&#xff1a;本文详解PCB基本概念以及实现MCU最小系统原理图的绘制&#xff08;原理图包括MCU芯片GD32F103C8T6、外部晶振、输出端口、USB输入口、5v转3v3稳压输出、复位按键、唤醒按键、LED&#xff09;。为本专栏后面章节实现PCB绘制做准备。 最终绘制的原理图如下所示&…