JAVA Future类详解及Thread线程是如何运行Future类的

news/2024/10/17 12:32:09/

一、Future基本介绍

        Future(java.util.concurrent Interface Future<V>)表示异步计算的结果。Future接口提供了检查计算是否完成、检查计算是否被取消、等待计算完成并获取计算结果等方法。

        在并发编程中,我们经常用到非阻塞的模型,但继承thread类和实现runnable接口,都无法保证获取到之前的执行结果。而通过实现Callback接口,并用Future可以来接收多线程的执行结果。

        Future表示一个可能还没有完成的异步任务的结果,针对这个结果可以添加Callback以便在任务执行成功或失败后作出相应的操作。

二、Future使用方法

public static void main(String[] args) throws ExecutionException, InterruptedException {Callable call = new Callable<String>(){@Overridepublic String call() throws Exception {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return "我被调用";}};FutureTask<String> future = new FutureTask<String>(call);new Thread(future).start();System.out.println(future.get());
}

        返回结果“我被调用” 

        接下来我们就围绕这这段代码看看整体的运行流程。

        我们这里主要关注的类是Callable FutureTask两个类

三、Callable类

         Callable是个支持泛型的函数式接口,里面有个call()方法

四、FutureTask继承体系

        RunnableFuture是个组合接口,继承了Future和Runnable两个接口,FutureTask实现了RunnableFuture接口,所以FutureTask拥有Future和Runnable两个接口的功能,我们知道Runnable接口是个函数式接口,里面只有一个run方法,我们重点看下Future这个类

五、Future类接口说明

/*** 方法可以用来停止一个任务,如果任务可以停止(通过mayInterruptIfRunning来进行判断),则可以返回true,* 如果任务已经完成或者已经停止,或者这个任务无法停止,则会返回false* 注意:mayInterruptIfRunning不一定会影响取消,要看具体实现,concurrent包里面部分类是不受该参数影响的,如CompletableFuture
*/
boolean cancel(boolean mayInterruptIfRunning);/*** 任务是否已经取消*/
boolean isCancelled();/*** 任务是否已经完成*/
boolean isDone();/*** 获取任务返回值,未执行完成则会阻塞等待结果*/
V get() throws InterruptedException, ExecutionException;/*** 指定超时时间,规定时间未获取结果则抛出TimeoutException*/
V get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;

六、FutureTask的主要实现

        我们知道我们调用了Thread的start()方法之后线程进入就绪状态,在线程获取运行资源之后会调用run()方法,所以我们就从这里入手,看看FutureTask的run()方法:

public void run() {if (state != NEW ||!RUNNER.compareAndSet(this, null, Thread.currentThread()))return;try {// 这里是初始化我们传入的callable对象Callable<V> c = callable;if (c != null && state == NEW) {V result;boolean ran;try {// 调用callable的call方法并获取返回结果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);}
}

        由上面的代码我们可以看到run()方法在执行的时候调用了我们传入的Callable对象的call()方法,并在成功执行后获取返回结果并对返回结果做封装,接下来我们看看封装返回结果的set()方法:

protected void set(V v) {if (STATE.compareAndSet(this, NEW, COMPLETING)) {// 将返回结果传到outcome参数中outcome = v;STATE.setRelease(this, NORMAL); // final statefinishCompletion();}
}

        FutureTask将Callable的call()方法的运行的返回结果传到outcome参数中,至此这个调用过程也结束了,我们看看父类Future的get方法的实现是如何获取返回参数的:

public V get() throws InterruptedException, ExecutionException {int s = state;if (s <= COMPLETING)s = awaitDone(false, 0L);return report(s);
}

        跟进去report()方法:

private V report(int s) throws ExecutionException {Object x = outcome;if (s == NORMAL)// 返回outcome对象return (V)x;if (s >= CANCELLED)throw new CancellationException();throw new ExecutionException((Throwable)x);
}

        至此,我们就跟完了整个调用流程了。


http://www.ppmy.cn/news/51181.html

相关文章

SpringBoot入门篇

SpringBoot入门 一、Maven项目二、HTTP协议2.1、协议概述2.2、请求协议2.3、响应协议2.3、协议解析 三、Web服务器 -TomCat3.1、Tomcat简介3.2、Tomcat使用3.3、内嵌Tomcat 四、请求响应4.1、请求4.1.1、postman4.1.2、简单参数4.1.3、实体参数4.1.4、数组集合参数4.1.5、日期参…

【FPGA-DSP】第九期:音频信号处理

从本文开始将记录一些简单的音频信号处理算法在System Generator中的实现方法。本文将介绍如何搭建音频信号的采集与输出模型。 音频信号属于一维信号&#xff0c;一些基本概念如下&#xff1a; 采样频率&#xff1a;根据奈奎斯特采样定理&#xff0c;采样频率Fs应该不低于声…

Nmap学习简记

Nmap主机发现 nmap -sn CIDR 对该网络中的所有主机进行ip扫描&#xff0c;以此来发现网络主机存活。 Nmap主机发现结果输出 nmap -sn CIDR -oX test.xml 将扫描结果输出到test.xml文件中方便以后使用。 Nmap端口探测技巧 nmap -p80 DNS 对某个端口进行探测 nmap -p80,…

【工作总结】后端开发人员的坏习惯

文章目录 前言一、不遵循项目规范二、用复杂SQL语句来解决问题三、缺少全局把控思维&#xff0c;只关注某一块业务四、函数复杂冗长,逻辑混乱五、缺乏主动思考&#xff0c;拿来主义六、核心业务逻辑,缺少相关日志和注释七、修改代码&#xff0c;缺少必要测试八、需求没理清&…

Yolov8损失函数改进:Wasserstein Distance Loss,助力小目标涨点

论文名称:《A Normalized Gaussian Wasserstein Distance for Tiny Object Detection》 作者:Jinwang Wang、Chang Xu、Chang Xu、Lei Yu 论文地址:https://arxiv.org/abs/2110.13389 小目标检测是一个非常具有挑战性的问题,因为小目标只包含几个像素大小。作者证明,由于…

【Python】【进阶篇】9、Django路由系统精讲

目录 Django路由系统精讲1. Django 路由系统应用1&#xff09;配置第一个URL实现页面访问2&#xff09;正则与正则分组使用3&#xff09;正则捕获组使用 2. path()与re_path() Django路由系统精讲 在《URL是什么》一节中&#xff0c;我们对 URL 有了基本的认识&#xff0c;在本…

mybatis3源码篇(1)——构建流程

mybatis 版本&#xff1a;v3.3.0 文章目录 构建流程SqlSessionFactoryBuilderXMLConfigBuildertypeAliasesElementtypeHandlerElementmapperElementMapperRegistry MappedStatementMapperAnnotationBuilderXMLMapperBuilderMapperBuilderAssistant SqlSessionFactorySqlSession…

数据结构(数组、链表、栈、队列、树)

文章目录 1.数组1.1数组的特点1.2自定义数组 2.链表2.1链表的特点2.2自定义链表2.2.1自定义单向链表2.2.2自定义双向链表 3.栈3.1栈的特点3.2 Stack使用举例3.3 自定义栈 4. 队列5. 树与二叉树5.1 树的理解5.2 二叉树的基本概念5.3 二叉树的遍历5.4 经典二叉树和红黑树5.5 二叉…