当前位置: 首页 > news >正文

FutureTask底层实现分析

文章目录

  • 前言
  • 一、FutureTask 的底层实现
  • 二、FutureTask核心方法run
  • 二、相关c++实现源码


前言

FutureTask 是 Java 的并发工具类,它继承了 Future 和 Runnable 的特性。它允许在一个单独的线程中执行一个任务,并可以在另一个线程中通过FutureTask.get()获取该任务的结果。类图如下:
在这里插入图片描述


一、FutureTask 的底层实现

FutureTask 的底层实现主要包括以下几个部分:
任务执行:FutureTask 内部维护了一个 Runnable 任务,当调用 FutureTask 的 run 方法时,这个任务会被执行。这个任务是在 FutureTask 实例被创建时传入的。
结果存储:任务执行的结果被存储在内部的一个 volatile 变量中。由于 volatile 保证了可见性,因此其他线程可以立即看到最新的结果。
状态管理:FutureTask 维护了一个内部状态,包括 NOT_RUNNING、RUNNING 和 DONE。这个状态用于跟踪任务是否正在运行或者已经完成。
阻塞等待:当其他线程调用 FutureTask 的 get 方法时,如果任务还没有完成,这个线程会被阻塞,直到任务完成并且结果可用。
异常处理:如果任务在执行过程中抛出了异常,那么这个异常会被捕获并存储在 FutureTask 中。调用 get 方法时,如果任务完成并且结果异常,那么这个异常会被重新抛出。

二、FutureTask核心方法run

代码如下:

public void run() {
// state != NEW说明该任务已经执行过或被cancel,非NEW状态,就不处理了
// compareAndSwapObject CAS原子比较this对象指定位置字段,若是期望值null,则更新该字段为当前线程,失败就返回
if (state != NEW ||!UNSAFE.compareAndSwapObject(this, runnerOffset,null, Thread.currentThread()))return;try {Callable<V> c = callable;if (c != null && state == NEW) {V result;boolean ran;try {// 执行任务逻辑result = c.call();ran = true;} catch (Throwable ex) {result = null;ran = false;setException(ex);}if (ran)set(result);}} finally {// runner must be non-null until state is settled to// prevent concurrent calls to run()runner = null;// state must be re-read after nulling runner to prevent// leaked interruptsint s = state;if (s >= INTERRUPTING)handlePossibleCancellationInterrupt(s);}
}

UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread()))
compareAndSwapObject将当前线程赋值给成员变量 Thread runner;
runnerOffset 为FutureTask.class对象的runner的偏移量
compareAndSwapObject 方法其实比较的就是两个 Java Object 的地址,如果相等则将新的地址(Java Object)赋给该字段。

二、相关c++实现源码

C++代码如下:

virtual jboolean compareAndSwapObject(::java::lang::Object *, jlong, ::java::lang::Object *, ::java::lang::Object *);
// natUnsafe.cc
static inline bool
compareAndSwap (volatile jobject *addr, jobject old, jobject new_val)
{jboolean result = false;spinlock lock;// 如果字段的地址与期望的地址相等则将字段的地址更新if ((result = (*addr == old)))*addr = new_val;return result;
}// natUnsafe.cc
jboolean
sun::misc::Unsafe::compareAndSwapObject (jobject obj, jlong offset,jobject expect, jobject update)
{// 获取字段地址并转换为字符串jobject *addr = (jobject*)((char *) obj + offset);// 调用 compareAndSwap 方法进行比较return compareAndSwap (addr, expect, update);
}

底层的实现总结来说:
通过我们传入的字段在对象中的偏移量来获取到字段的地址(对象首地址 + 字段在对象中的偏移量);然后调用 CompareAndSwap 方法比较字段的地址是否与我们期望的地址相等,如果相等则使用我们传入的新地址更新字段的地址;


相关文章:

  • jquery的9大选择器
  • C++面试:表结构设计规范
  • 腾讯云SDK并发调用优化方案
  • 迅为LS2K0500开发板引出PCI接口,可扩展显卡、网卡、声卡、视频卡、SATARAID等
  • 突破编程_C++_面试(基础知识(一))
  • LeetCode2670. Find the Distinct Difference Array
  • Golang 流媒体服务器lalserver使用指南
  • Wpf 使用 Prism 实战开发Day16
  • 第七篇:node中间件详解
  • 指针的深入了解6
  • 软件工程知识梳理4-详细设计
  • 【项目日记(六)】第二层: 中心缓存的具体实现(下)
  • I/O..
  • Linux 入门基础知识(一)—— Linux的基本使用
  • C++ ffmpeg RTSP 视频推流实现, arm linux平台
  • 【mysql】环境安装、服务启动、密码设置
  • 2017年终总结、随想
  • Apache的80端口被占用以及访问时报错403
  • golang中接口赋值与方法集
  • happypack两次报错的问题
  • HTTP--网络协议分层,http历史(二)
  • JavaScript函数式编程(一)
  • java第三方包学习之lombok
  • js
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 好的网址,关于.net 4.0 ,vs 2010
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 猫头鹰的深夜翻译:Java 2D Graphics, 简单的仿射变换
  • 使用权重正则化较少模型过拟合
  • 文本多行溢出显示...之最后一行不到行尾的解决
  • 协程
  • 一道面试题引发的“血案”
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 最近的计划
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • zabbix3.2监控linux磁盘IO
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • !!Dom4j 学习笔记
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • (26)4.7 字符函数和字符串函数
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (二十四)Flask之flask-session组件
  • (分享)自己整理的一些简单awk实用语句
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (四)linux文件内容查看
  • (转)setTimeout 和 setInterval 的区别
  • (转载)深入super,看Python如何解决钻石继承难题
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • .NET 4.0中的泛型协变和反变
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .net core 连接数据库,通过数据库生成Modell
  • .net mvc部分视图
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .NET开源快速、强大、免费的电子表格组件
  • .net连接oracle数据库