【Java并发】聊聊Future如何提升商品查询速度

java中可以通过new thread、实现runnable来进行实现线程。但是唯一的缺点是没有返回值、以及抛出异常,而callable就可以解决这个问题。通过配合使用futuretask来进行使用。
并且Future提供了对任务的操作,取消,查询是否完成,获取结果。

Demo

        FutureTask<Integer> futureTask = new FutureTask<Integer>(() -> {Thread.sleep(10000);System.out.println("调用三方翻译接口");return 1024;});new Thread(futureTask).start();Integer integer = futureTask.get();
//        Integer integer = futureTask.get(1, TimeUnit.SECONDS);while (true) {if (futureTask.isDone()) {System.out.println("完成任务");break;} else {System.out.println("执行中,稍等.");}}Integer x = futureTask.get();System.out.println(x);

在这里插入图片描述

实现原理

FutureTask核心代码

基本属性

     /* *  Possible state transitions:* 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; // Callable的结果,正常封装给当前FutureTaskprivate static final int NORMAL       = 2; // Normal任务正常结束private static final int EXCEPTIONAL  = 3; // 执行任务时,发生了异常private static final int CANCELLED    = 4; // 任务被取消了private static final int INTERRUPTING = 5; // 线程的中断状态,被设置为了ture private static final int INTERRUPTED  = 6; // 线程被中断了// 当前要执行的任务private Callable<V> callable;// 存放任务返回结果的属性,也就是futureTask.get 需要获取的结果private Object outcome; // 执行任务的线程private volatile Thread runner;// 单向链表,存放通过get方法挂起等待的线程private volatile WaitNode waiters;

任务

当线程start() 之后其实执行的就是call()方法。也就是通过futureTask的run方法执行的call()方法。

    // run方法的执行流程,最终会执行callable的call方法public void run() {// 保证任务的状态是NEW才执行,或者CAS将当前线程设置为runner.if (state != NEW ||!UNSAFE.compareAndSwapObject(this, runnerOffset,null, Thread.currentThread()))return;try {// 准备执行任务Callable<V> c = callable;// 任务不为null 并且state==newif (c != null && state == NEW) {V result; // 返回的结果boolean ran; // 任务执行是否正常结束try { // 调用callable的call方法。result = c.call();ran = true; // 正常结束 ran = true} catch (Throwable ex) {result = null; // 异常结果为null ran = false; // 异常结束 ran = falsesetException(ex); // 设置异常信息}if (ran) // 正常执行结束,设置返回结果set(result);}} finally {// 执行完毕 或者异常 ,都将runner设置为null runner = null;// 拿到状态int s = state;// 如果中断 要做一些事情if (s >= INTERRUPTING)handlePossibleCancellationInterrupt(s);}}//设置result值protected void set(V v) {// cas设置state为 new-completingif (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {outcome = v; // 返回结果给outcomeUNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state// 下面说finishCompletion();}}

get

get方法获取返回结果,到挂起的位置

    public V get() throws InterruptedException, ExecutionException {//拿状态int s = state;//满足未完成状态 就需要等待if (s <= COMPLETING)// 挂起线程,等待拿结果。s = awaitDone(false, 0L);return report(s);}//线程要等待任务执行结束,等待任务执行的状态大于completing状态private int awaitDone(boolean timed, long nanos)throws InterruptedException {// dealline get() 就是0 ,如果是get(time,unit) 追加当前系统时间final long deadline = timed ? System.nanoTime() + nanos : 0L;// 构建waitNode WaitNode q = null;boolean queued = false;//死循环for (;;) {//判断get线程是否中断了if (Thread.interrupted()) {//将当前节点从waiter中移除removeWaiter(q);//并且抛出中断异常throw new InterruptedException();}// 拿到现在任务的状态int s = state;// 判断任务是否执行完毕if (s > COMPLETING) {// q != null。表示设置过了 直接移除waitNode线程if (q != null)q.thread = null;//返回当前任务状态return s;}// 如果任务的状态处于completing else if (s == COMPLETING) // cannot time out yet//让步Thread.yield();else if (q == null)// 线程状态还是new  call方法可能还没有执行 准备挂起线程// 封装waitNode存放当前线程q = new WaitNode();else if (!queued)// 如果waitNode还没有排在waiters中,就拍进来(头插法) cas修改queued = UNSAFE.compareAndSwapObject(this, waitersOffset,q.next = waiters, q);// 如果get(time,unit)挂起线程方式else if (timed) {// 计算挂起时间nanos = deadline - System.nanoTime();// 挂起时间 是否小于等于0 if (nanos <= 0L) {// 移除waiter 当前noderemoveWaiter(q);// 返回任务状态return state;}//正常指定挂起时间即可LockSupport.parkNanos(this, nanos);}else//get()挂起线程的方式LockSupport.park(this);}}

finishCompletion唤醒线程

线程挂起后,如果任务执行完毕,由finishCompletioon唤醒线程

    private void finishCompletion() {// assert state > COMPLETING;for (WaitNode q; (q = waiters) != null;) {// 拿到第一个阶段,cas的方式修改 将其设置为null if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {for (;;) {// 拿到q线程信息Thread t = q.thread;// 线程信息不为空if (t != null) {// 将waitNode的thread设置为null q.thread = null;// 唤醒这个线程LockSupport.unpark(t);}//往后遍历 接着唤醒WaitNode next = q.next;if (next == null)break;q.next = null; // unlink to help gc//执行next的waitNode q = next;}break;}}//拓展方法 没任何实现 done();//任务执行完毕callable = null;        // to reduce footprint}

report

// 任务结束。
private V report(int s) throws ExecutionException {// 拿到结果Object x = outcome;// 判断是正常返回结束if (s == NORMAL)// 返回结果return (V)x;// 任务状态是大于取消if (s >= CANCELLED)// 甩异常。throw new CancellationException();// 扔异常。throw new ExecutionException((Throwable)x);
}// 正常返回 report
// 异常返回 report
// 取消任务 report
// 中断任务 awaitDone

流程图

在这里插入图片描述

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

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

相关文章

代理模式-C#实现

该实例基于WPF实现&#xff0c;直接上代码&#xff0c;下面为三层架构的代码。 目录 一 Model 二 View 三 ViewModel 一 Model using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace 设计模式练…

【Linux】进程间通信——信号量

让大家久等啦&#xff0c;本期我们来讲讲Linux系统中的信号量 目录 一、引入 二、认识信号量 2.1 信号量的概念 2.2 信号量的内核结构 三、关于信号量的接口 3.1 semget 3.2 ipcs -s 3.3 ipcrm -s 3.4 semctl 3.5 semop 四、理解IPC 一、引入 在开始之前我们先来认…

2023.1.21 关于 Redis 主从复制详解

目录 引言 单点问题 分布式系统 主从模式 配置 Redis 主从结构 断开主从关系 切换主从关系 补充知识点一 只读 网络延迟 拓扑结构 一主一从 一主多从 树形主从结构 主从复制的基本流程 数据同步 replicationid offset pzync 运行流程 具体流程 补充知识点二…

C. Doremy‘s City Construction(二分图问题)

思路&#xff1a;把集合划分成两部分,一部分中每个数都比另一部分小,这两部分连成一个完全二分图,这种情况是最优的,还需要特判所有数都相等的情况. 代码&#xff1a; void solve(){int n;cin >> n;vector<int>a(n 1);for(int i 1;i < n;i )cin >> a[…

如何使用iPhone或iPad上的二维码共享Wi-Fi密码?这里有详细步骤

你有没有想过在不泄露网络密码的情况下与客人共享你的家庭或工作Wi-Fi?你肯定不是第一个这样想的人,我们很高兴地通知你,多亏了以下这个的变通方法,你现在可以使用iPhone或iPad做到这一点。 通常,如果你想让其他人访问网络,你需要共享你的Wi-Fi密码。苹果通过引入与任何…

python 学习之 re库的基本使用(正则匹配)上

目录 一、基本用法 二、函数介绍 1、match函数 2、search 函数 3、compile 函数 4、findall 和 finditer 函数 5、sub 函数和 subn 函数 6、split 函数 一、基本用法 首先我们需要引入 re 库 代码基本框架使用两行代码实现 测试代码&#xff1a; import reret re.m…

vue 本地中导入 maptalks

1、进入 github 中 maptalks 文件下载页面&#xff08;https://github.com/maptalks/maptalks.js/releases&#xff09; 这里可能会有朋友应为网络问题打不开 github &#xff0c;可以查看作者另一篇关于解决该问题的文章&#x1f449;GitHub 打不开问题解决 2、将下载好的文件…

5V摄像机镜头驱动芯片GC6208,为什么可以替代AN41908,适用于摄像机镜头上

GC6208是一个镜头电机驱动IC摄像机和安全摄像机。该装置集成了一个由PID控制的可变光圈直流电机驱动器和两个通道的扫描隧道显微镜电机驱动器&#xff0c;用于变焦和聚焦控制。AN41908A是一款用于摄像机和安全摄像机的镜头马达驱动IC&#xff0c;具有lris控制功能。电压驱动系统…

.zip 文件和 .tar.gz文件 的区别

tgz和zip两种压缩格式,其实这两个压缩文件里面包含的内容是一样的,只是压缩格式不一样. tar.gz格式的文件比zip文件要小不少。tar.gz压缩格式用于unix的操作系统, 而zip用于windows的操作系统,但在windows系统中WinRar工具同样可以解压缩tar.gz格式的。 扩展&#xff1a; z…

仿真机器人-深度学习CV和激光雷达感知(项目2)day5【作业1与答案1】

文章目录 前言作业1答案1 前言 &#x1f4ab;你好&#xff0c;我是辰chen&#xff0c;本文旨在准备考研复试或就业 &#x1f4ab;本文内容是我为复试准备的第二个项目 &#x1f4ab;欢迎大家的关注&#xff0c;我的博客主要关注于考研408以及AIoT的内容 &#x1f31f; 预置知识…

在Rust中编写自定义Error

前言 之前我们聊过&#xff0c;Result<T, E> 类型可以方便地用于错误传导&#xff0c;Result<T, E>是模板类型&#xff0c;实例化后可以是各种类型&#xff0c;但 Rust 要求传导的 Result 中的 E 是相同类型的&#xff0c;或者能够自动转化为相同类型。比如&#…

【Jetbrains全家桶】PyCharm专业版学生用户申请(学信网)+Toolbox App安装配置教程(修改系统、配置和日志目录)

文章目录 一、Jetbrains学生用户免费使用1. [Jetbrains官网](https://www.jetbrains.com.cn/en-us/)新申请更新资料申请界面 2. [学信网](https://www.chsi.com.cn/xlcx/index.jsp)教育部学籍在线验证报告本人身份核验申请报告 二、安装Toolbox App[Toolbox App](https://www.j…

Qt 拖拽事件示例

一、引子 拖拽这个动作,在桌面应用程序中是非常实用和具有很友好的交互体验的。我们常见的譬如有,将文件拖拽到某个窗口打开,或者拖拽文件到指定位置上传;在绘图软件中,选中某个模板、并拖拽到画布上,画布上变回绘制该模板的图像… 诸如此类,数不胜数。 那么,在Qt中我…

开源项目Git Commit规范与ChangeLog

一&#xff0c;conventional commit(约定式提交) Conventional Commits 是一种用于给提交信息增加人机可读含义的规范。它提供了一组用于创建清晰的提交历史的简单规则。 1.1 作用 自动化生成 CHANGELOG基于提交类型&#xff0c;自动决定语义化的版本变更向项目相关合作开发…

shell脚本—循环语句

文章目录 循环语句循环含义1、for2、whilewhile循环 3、until4、双重循环及跳出循环 循环语句 echo命令&#xff1a;标准输出或提取shell变量的值 标准输出 [rootlocalhost ~]#echo 123456|passwd --stdin zhangsan 更改用户 zhangsan 的密码 。 passwd&#xff1a;所有的身…

SWMM模型INP解析

.INP文件解析 [OPTIONS]&#xff1a;SWMM软件运行前需要设置的参数 [RAINGAGES]雨水节点&#xff0c;核心设置雨水时间序列&#xff0c;可为INP内部数据也可为外部txt数据&#xff0c;TIMESERIES对应【TIMESERIES】模块&#xff0c;TS_1为时间序列名称 [TIMESERIES]&#xff0…

部署幻兽帕鲁联机服务器需要怎样配置的云服务器?

随着互联网技术的快速发展&#xff0c;多人在线游戏逐渐成为人们休闲娱乐的重要方式。作为一款备受欢迎的游戏&#xff0c;幻兽帕鲁以其独特的玩法吸引了大量玩家。为了获得更好的游戏体验&#xff0c;许多玩家选择在云服务器上自行部署幻兽帕鲁联机服务器。本文将详细介绍部署…

设置模式之责任链模式

目录 1.概述 2.结构 3.实现 4.总结 1.概述 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为性设计模式&#xff1b;它为请求创建了一个接收者对象的链&#xff0c;允许你将请求沿着处理者链进行发送。 收到请求后&#xff0c; 每个处理者均…

图像处理python基础

array 读取图片 tensor 模型预测 一般过程&#xff1a;读取数据np->tensor->model->result->np->画图 shape确保图像输入输出尺寸正确 读取图片 将在GPU上运行的tensor类型转变成在CPU上运行的np类型 三类计算机视觉任务的输入&#xff1a; 分类&#xff1…

【软考问题】-- 1 - 知识精讲 - 项目管理理论

一、基本问题 1&#xff1a;项目的特点是什么&#xff1f; 临时性&#xff1a;是指项目有明确的起点和终点&#xff0c;从项目启动到项目收尾。项目目标实现后&#xff0c;项目收尾工作完成即标志着项目结束。独特性&#xff1a;项目是独特的&#xff0c;之前没有做过的&#x…