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;适合各种人群参与。接下来…

JavaWeb 监听器

Javaweb监听器是一种特殊的类&#xff0c;用于监听Web应用程序中的事件和对象。它可以监听Web应用程序的启动和关闭事件&#xff0c;会话的创建和销毁事件&#xff0c;以及请求和响应的事件等。监听器可以在特定事件发生时执行一些特定的操作&#xff0c;比如记录日志、初始化资…

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

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

Ant Design中Tree使用defaultExpandAll属性后不会默认展开所有节点怎么办?

最近做前端项目时&#xff0c;使用到了 tree 组件&#xff0c;选择使用 Ant Design 中的 tree 组件&#xff0c;默认所有节点初始时全部展开&#xff0c;使用 defaultExpandAll 属性。但是显示的时候&#xff0c;一个节点都没展开。于是调研了一下这个问题。发现有以下问题&…

leetcode刷题(python)——(六)

01.03.07 练习题目&#xff08;第 06 天&#xff09; 1. 0506. 相对名次 1.1 题目大意 描述&#xff1a;给定一个长度为 n n n 的数组 s c o r e score score。其中 s c o r e [ i ] score[i] score[i] 表示第 i i i 名运动员在比赛中的成绩。所有成绩互不相同。 要求&…

在 Vue中,v-for 指令的使用

在 Vue中&#xff0c;v-for 指令用于渲染一个列表&#xff0c;基于源数据多次渲染元素或模板块。它对于展示数组或对象中的数据特别有用。 数组渲染 假设你有一个数组&#xff0c;并且你想为每个数组元素渲染一个 <li> 标签&#xff1a; <template> <ul>…

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…

Golang context 原理分析

1. 说在前面2. 场景分析 2.1 链式传递2.2 主动取消2.3 任务超时2.4 数据存储 3. 源码解读 3.1 一个核心数据结构 3.1.1 Context 3.2 四种具体实现 3.2.1 emptyCtx3.2.2 cancelCtx3.2.3 timerCtx3.2.4 valueCtx 3.3 六个核心方法 3.3.1 Background() && TODO()3.3.2 Wit…

如何在在wordpress安装百度统计

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

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

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

什么是Dubbo及其主要作用

在微服务架构日益盛行的今天&#xff0c;RPC&#xff08;远程过程调用&#xff09;技术成为了实现服务间通信的关键手段。而Dubbo&#xff0c;作为一款高性能、轻量级的开源Java RPC框架&#xff0c;受到了广大开发者的青睐。那么&#xff0c;Dubbo究竟是什么呢&#xff1f;它的…

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…

动态规划相关

动态规划相关 力扣509 斐波那契数列 完全递归解法 / 设置备忘录减少递归次数解法 都是 自顶向下力扣 509 斐波那契数列 动态规划 自底向上 力扣509 斐波那契数列 完全递归解法 / 设置备忘录减少递归次数解法 都是 自顶向下 public int fib(int n) {/** if(n<2){* return n;…

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

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