Callable and FutureTask

Callable

由关系图可知,Callable和Runnable一样,也是一个函数式接口,可以使用Lambda表达式

与之不同的是,其内部的call()方法可以抛出异常且能return一个返回值

 Callable<Object> callable = new Callable() {@Overridepublic Object call() throws Exception {System.out.println("执行call方法");return null;}};

FutureTask

FutureTask构造方法源码:public FutureTask(Callable<V> callable) {if (callable == null)throw new NullPointerException();this.callable = callable;this.state = NEW;       // ensure visibility of callable}public FutureTask(Runnable runnable, V result) {this.callable = Executors.callable(runnable, result);this.state = NEW;       // ensure visibility of callable}

Future接口方法

 //mayInterruptIfRunning:是否取消正在执行但还有执行完毕的任务 //true:取消任务 返回true//false:让任务执行完毕 返回falseboolean cancel(boolean mayInterruptIfRunning);//任务是否被取消boolean isCancelled();//任务是否完成 //完成可能是由于正常终止、异常或取消 --- 在所有这些情况下,此方法将返回 trueboolean isDone();//得到任务返回值,如果未执行的话会阻塞等待V get() throws InterruptedException, ExecutionException;//设置最大阻塞时间,如果超过最大阻塞时间后还是没有执行完任务,抛出TimeOutExceptionV get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;

根据上方关系图我们可知

FutureTask可以包装Runnable/Callable对象-----构造方法

FutureTask实现了Runnable接口 ,故其可以作为Runnable被线程执行

notice:线程执行的是FutureTask类包装的Callable对象下的call()方法

public static void main(String[] args) throws ExecutionException, InterruptedException {//使用Callable进行1-100相加数和Callable<Long> callable = new Callable<Long>() {@Overridepublic Long call() throws Exception {System.out.println("开始执行子线程相加内容");long sum = 0;for(int i = 1; i <= 100; i++){sum += i;}return sum;}};FutureTask<Long> futureTask = new FutureTask<>(callable);Thread t = new Thread(futureTask);//真正执行call方法的是线程 所以必须要启动线程后 call方法才会执行//t.start();//相当于t.join操作System.out.println("futureTask.get()得到call方法的函数返回值:"+futureTask.get()); //如果没有call方法内容没有执行完 get方法会一直阻塞
}

此时没有执行t.start操作,futureTask.get()方法就会一直阻塞

反之执行t.start;


 
  //使用Callable进行1-100相加数和Callable<Long> callable = new Callable<Long>() {@Overridepublic Long call() throws Exception {Thread.sleep(3000);System.out.println("开始执行子线程相加内容");long sum = 0;for(int i = 1; i <= 100; i++){sum += i;}return sum;}};FutureTask<Long> futureTask = new FutureTask<>(callable);Thread t = new Thread(futureTask);//真正执行call方法的是线程 所以必须要启动线程后 call方法才会执行t.start();long begin = System.currentTimeMillis();//相当于t.join操作System.out.println("futureTask.get()得到call方法的函数返回值:"+futureTask.get()); //如果没有call方法内容没有执行完 get方法会一直阻塞long end = System.currentTimeMillis();System.out.println("阻塞时间:"+ (end -begin));}

上述代码中,我们在call方法中休眠了三秒,由于当get方法任务没有执行完时,就会阻塞,故主线程被三秒,所以get()操作类似于join方法


get():

我们知道,当线程在休眠时被终止时,会触发sleep内部异常,在Runnable中,触发异常后并不会终止进程,而是将线程提前唤醒,且将终止标志位重新设置为false,后续的操作由程序员的代码决定 

public static void main(String[] args) {Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {for(int i = 0; i < 3; i++){System.out.println("Hello World");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();System.out.println("触发skeep interrupted异常 后续执行操作由我决定");}}}});t1.start();t1.interrupt();System.out.println("线程是否被终止:"+t1.isInterrupted());}

即使触发了异常,但还是继续完成了runnable中的run方法


但在Callable中,如果线程被休眠时被唤醒,FutureTask.get()方法就会直接报错且退出程序

public static void main(String[] args) throws ExecutionException, InterruptedException {Callable<String> callable = new Callable<String>() {@Overridepublic String call() throws Exception {System.out.println("你好");Thread.sleep(1000);return "我要报错拉";}};FutureTask task = new FutureTask(callable);Thread t = new Thread(task);t.start();t.interrupt();//非正常终止 --- 休眠时终止System.out.println("isDone:"+task.isDone());System.out.println(task.get());}


但如果仅仅是启动线程(没有FutureTask.get()操作),那么不会报错,但会直接终止线程

 public static void main(String[] args) throws ExecutionException, InterruptedException {Callable<String> callable = new Callable<String>() {@Overridepublic String call() throws Exception {for(int i = 0; i < 3; i++){System.out.println("你好");Thread.sleep(1000);}return "我要报错拉";}};FutureTask task = new FutureTask(callable);Thread t = new Thread(task);t.start();t.interrupt();//非正常终止 --- 休眠时终止System.out.println("isDone:"+task.isDone());}


超时get():
 public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {//超时get方法Callable<String> callable = new Callable<String>() {@Overridepublic String call() throws Exception {Thread.sleep(2000);System.out.println("任务继续执行");return "ok";}};FutureTask futureTask = new FutureTask(callable);Thread t = new Thread(futureTask);t.start();//若超出时间 报TimeoutException异常 call方法中的内容继续进行  //无法取到call方法中的返回值了System.out.println(futureTask.get(1, TimeUnit.SECONDS));}

.

超时后call方法中的任务还是会继续进行,但无法通过get方法获得call方法的返回值了


cancel():
public static void main(String[] args) {Callable<Integer> callable = new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int sum = 0;for(int i = 0; i <= 10; i++){sum += i;}return sum;}};FutureTask<Integer> futureTask = new FutureTask<>(callable);Thread t = new Thread(futureTask);t.start();//取消任务  参数mayInterruptIfRunning是否取消正在运行的任务  其内部实际上还是通过interrupt方法System.out.println("cancel:"+futureTask.cancel(true));//任务是否被取消System.out.println("isCancelled:"+futureTask.isCancelled());//任务是否执行完成//如果此任务已完成,则返回 true。完成可能是由于正常终止、异常或取消 -- 在所有这些情况下,此方法将返回 trueSystem.out.println("isDone:"+futureTask.isDone());}


 //取消任务  参数mayInterruptIfRunning是否取消正在运行的任务  其内部实际上还是通过interrupt方法System.out.println("cancel:"+futureTask.cancel(true));//在取消任务后 调用get方法 此时不能返回call方法返回值 且会抛出异常 退出程序System.out.println("after cancel:"+ futureTask.get());


使用线程池执行Callable
//利用线程池执行public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService service = Executors.newFixedThreadPool(10);//execute Runnable command//submit Future<V> future//这里是Callable 只能使用submit Runnable/Callable都可以 返回值是Future<?> / 不能使用execute:RunnableFuture<String> future = service.submit(new Callable<String>() {@Overridepublic String call() throws Exception {return "Hello World";}});System.out.println(future.get());service.shutdown();}

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

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

相关文章

网上赚钱新姿势:日赚二三十,十大靠谱平台任你选!

互联网时代下&#xff0c;网络兼职已成为许多人追求额外收入的热门选择。互联网的广泛普及与发展&#xff0c;不仅让人们轻松获取海量信息&#xff0c;更为我们提供了多样化的兼职机会。这些兼职工作不仅时间自由&#xff0c;而且种类繁多&#xff0c;适合各种人群参与。接下来…

【AR开发示例】实现AR管线巡检

写在前面的话 这是一篇旧文档&#xff0c;代码仓库见 https://gitee.com/tanyunxiu/AR-pipe 本文档是基于超图移动端SDK的AR模块开发的示例&#xff0c;仅供参考&#xff0c;SDK在持续迭代中&#xff0c;相关描述可能有变化。 示例介绍 这是一个使用AR查看墙内管线的基础示…

Spring Cloud 运维篇1——Jenkins CI/CD 持续集成部署

Jenkins 1、Jenkins是什么&#xff1f; Jenkins 是一款开源 CI/CD 软件&#xff0c;用于自动化各种任务&#xff0c;包括构建、测试和部署软件。 Jenkins 支持各种运行方式&#xff0c;可通过系统包、Docker 或者一个独立的 Java 程序。 Jenkins Docker Compose持续集成流…

k8s安装,linux-ubuntu上面kubernetes详细安装过程

官方文档&#xff1a;https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/ 环境配置 该部分每个主机都要执行 如果你确定不需要某个特定设置&#xff0c;则可以跳过它。 设置root登录 sudo passwd root sudo vim /etc/ssh/sshd_config Perm…

HarmonyOS NEXT 使用XComponent + Vsync 实现自定义动画

介绍 XComponent 提供了应用在 native 侧调用 OpenGLES 图形接口的能力&#xff0c;本文主要介绍如何配合 Vsync 事件&#xff0c;完成自定义动画。在这种实现方式下&#xff0c;自定义动画的绘制不在 UI 主线程中完成&#xff0c;即使主线程卡顿&#xff0c;动画效果也不会受…

晶圆制造之MPW(多项目晶圆)简介

01、MPW是什么&#xff1f; 在半导体行业中&#xff0c;MPW 是 "Multi Project Wafer" 的缩写&#xff0c;中文意思是多项目晶圆。MPW 的主要思想是将使用相同工艺的多个集成电路设计放在同一晶圆片上进行流片&#xff08;即制造&#xff09;。这种方法允许多个设计共…

java学习笔记6

11. 类的封装 ​ 在Java中,**封装(Encapsulation)**是面向对象编程中的重要概念,它指的是将类的数据(属性)和行为(方法)绑定在一起,并对外部隐藏数据的具体实现细节,只通过公共方法来访问和操作数据。这有助于提高代码的安全性、可维护性和灵活性。 11.1 为什要封装 …

Python exe 文件反编译为 Python 脚本

文章目录 前言版本反编译Python 可执行文件&#xff08;.exe&#xff09;反编译打包一个简单的 .exe 可执行文件提取 pyc 文件使用脚本提取使用工具提取 将 .pyc 文件转换为 Python 脚本入口运行类非入口运行类转换补全后的 pyc 文件uncompyle6 反编译在线工具 可能遇到的问题P…

如何在在wordpress安装百度统计

前言 看过我的往期文章的都知道&#xff0c;我又建了一个网站&#xff0c;这次是来真的了。于是&#xff0c;最近在查阅资料时发现&#xff0c;有一款免费的软件可以帮我吗分析网站数据。&#xff08;虽然我的破烂网站压根没人访问&#xff0c;但是能装上的都得上&#xff0c;…

探索边缘计算:技术的新疆界

探索边缘计算&#xff1a;技术的新疆界 在当今迅速发展的数字化时代&#xff0c;云计算作为数据处理的主力军已广泛应用。但是&#xff0c;随着物联网&#xff08;IoT&#xff09;设备的急剧增加和数据生成速率的加快&#xff0c;云计算面临着种种挑战。边缘计算因此诞生&…

STL-list的使用及其模拟实现

在C标准库中&#xff0c;list 是一个双向链表容器&#xff0c;用于存储一系列元素。与 vector 和 deque 等容器不同&#xff0c;list 使用带头双向循环链表的数据结构来组织元素&#xff0c;因此list插入删除的效率非常高。 list的使用 list的构造函数 list迭代器 list的成员函…

深度神经网络(DNN)

通过5个条件判定一件事情是否会发生&#xff0c;5个条件对这件事情是否发生的影响力不同&#xff0c;计算每个条件对这件事情发生的影响力多大&#xff0c;写一个深度神经网络&#xff08;DNN&#xff09;模型程序,最后打印5个条件分别的影响力。 示例 在深度神经网络&#xf…

Matlab新手快速上手2(粒子群算法)

本文根据一个较为简单的粒子群算法框架详细分析粒子群算法的实现过程&#xff0c;对matlab新手友好&#xff0c;源码在文末给出。 粒子群算法简介 粒子群算法&#xff08;Particle Swarm Optimization&#xff0c;PSO&#xff09;是一种群体智能优化算法&#xff0c;灵感来源于…

目标检测YOLO数据集的三种格式及转换

目标检测YOLO数据集的三种格式 在目标检测领域&#xff0c;YOLO&#xff08;You Only Look Once&#xff09;算法是一个流行的选择。为了训练和测试YOLO模型&#xff0c;需要将数据集格式化为YOLO可以识别的格式。以下是三种常见的YOLO数据集格式及其特点和转换方法。 1. YOL…

计算机系统结构(二) (万字长文建议收藏)

计算机系统结构 (二) 本文首发于个人博客网站&#xff1a;http://www.blog.lekshome.top/由于CSDN并不是本人主要的内容输出平台&#xff0c;所以大多数博客直接由md文档导入且缺少审查和维护&#xff0c;如果存在图片或其他格式错误可以前往上述网站进行查看CSDN留言不一定能够…

大话设计模式-里氏代换原则

里氏代换原则&#xff08;Liskov Substitution Principle&#xff0c;LSP&#xff09; 概念 里氏代换原则是面向对象设计的基本原则之一&#xff0c;由美国计算机科学家芭芭拉利斯科夫&#xff08;Barbara Liskov&#xff09;提出。这个原则定义了子类型之间的关系&#xff0…

【人工智能基础】经典逻辑与归结原理

本章节的大部分内容与离散数学的命题、谓词两章重合。 假言推理的合式公式形式 R,R→P⇒PR,R∨P⇒P 链式推理 R→P,P→Q⇒R→QR∨P,P∨Q⇒R∨Q 互补文字&#xff1a;P和P 亲本子句&#xff1a;含有互补文字的子句 R∨P,P∨Q为亲本子句 注意&#xff1a; 必须化成析取范式…

命理八字之电子木鱼的代码实现

#uniapp# #电子木鱼# 不讲废话&#xff0c;上截图 目录结构如下图 功能描述&#xff1a; 点击一下&#xff0c;敲一下&#xff0c;伴随敲击声&#xff0c;可自动点击。自动点击需看视频广告&#xff0c;或者升级VIP会员。 疑点解答&#xff1a; 即animation动画的时候&…

Window中Jenkins部署asp/net core web主要配置

代码如下 D: cd D:\tempjenkins\src\ --git工作目录 dotnet restore -s "https://nuget.cdn.azure.cn/v3/index.json" --nuget dotnet build dotnet publish -c release -o %publishPath% --发布路径

Day08React——第八天

useEffect 概念&#xff1a;useEffect 是一个 React Hook 函数&#xff0c;用于在React组件中创建不是由事件引起而是由渲染本身引起的操作&#xff0c;比如发送AJAx请求&#xff0c;更改daom等等 需求&#xff1a;在组件渲染完毕后&#xff0c;立刻从服务器获取频道列表数据…