当前位置:网站首页>【高并发】2.8万字的Callable和Future面试知识点总结,看完我直接面进了字节跳动,原谅我有点飘了(中)
【高并发】2.8万字的Callable和Future面试知识点总结,看完我直接面进了字节跳动,原谅我有点飘了(中)
2022-06-29 10:36:00 【华为云】
大家好,我是冰河~~
在Java的多线程编程中,除了Thread类和Runnable接口外,不得不说的就是Callable接口Future接口了。使用继承Thread类或者实现Runnable接口的线程,无法返回最终的执行结果数据,只能等待线程执行完成。此时,如果想要获取线程执行后的返回结果,那么,Callable和Future就派上用场了。
注:文章全程高能,建议收藏,如果文章对你有点帮助,小伙伴们一键三连呀,谢谢啦~~
两种异步模型与深度解析Future接口
两种异步模型
在Java的并发编程中,大体上会分为两种异步编程模型,一类是直接以异步的形式来并行运行其他的任务,不需要返回任务的结果数据。一类是以异步的形式运行其他任务,需要返回结果。
1.无返回结果的异步模型
无返回结果的异步任务,可以直接将任务丢进线程或线程池中运行,此时,无法直接获得任务的执行结果数据,一种方式是可以使用回调方法来获取任务的运行结果。
具体的方案是:定义一个回调接口,并在接口中定义接收任务结果数据的方法,具体逻辑在回调接口的实现类中完成。将回调接口与任务参数一同放进线程或线程池中运行,任务运行后调用接口方法,执行回调接口实现类中的逻辑来处理结果数据。这里,给出一个简单的示例供参考。
- 定义回调接口
package io.binghe.concurrent.lab04;/** * @author binghe * @version 1.0.0 * @description 定义回调接口 */public interface TaskCallable<T> { T callable(T t);}便于接口的通用型,这里为回调接口定义了泛型。
- 定义任务结果数据的封装类
package io.binghe.concurrent.lab04;import java.io.Serializable;/** * @author binghe * @version 1.0.0 * @description 任务执行结果 */public class TaskResult implements Serializable { private static final long serialVersionUID = 8678277072402730062L; /** * 任务状态 */ private Integer taskStatus; /** * 任务消息 */ private String taskMessage; /** * 任务结果数据 */ private String taskResult; //省略getter和setter方法 @Override public String toString() { return "TaskResult{" + "taskStatus=" + taskStatus + ", taskMessage='" + taskMessage + '\'' + ", taskResult='" + taskResult + '\'' + '}'; }}- 创建回调接口的实现类
回调接口的实现类主要用来对任务的返回结果进行相应的业务处理,这里,为了方便演示,只是将结果数据返回。大家需要根据具体的业务场景来做相应的分析和处理。
package io.binghe.concurrent.lab04;/** * @author binghe * @version 1.0.0 * @description 回调函数的实现类 */public class TaskHandler implements TaskCallable<TaskResult> { @Overridepublic TaskResult callable(TaskResult taskResult) {//TODO 拿到结果数据后进一步处理 System.out.println(taskResult.toString()); return taskResult; }}- 创建任务的执行类
任务的执行类是具体执行任务的类,实现Runnable接口,在此类中定义一个回调接口类型的成员变量和一个String类型的任务参数(模拟任务的参数),并在构造方法中注入回调接口和任务参数。在run方法中执行任务,任务完成后将任务的结果数据封装成TaskResult对象,调用回调接口的方法将TaskResult对象传递到回调方法中。
package io.binghe.concurrent.lab04;/** * @author binghe * @version 1.0.0 * @description 任务执行类 */public class TaskExecutor implements Runnable{ private TaskCallable<TaskResult> taskCallable; private String taskParameter; public TaskExecutor(TaskCallable<TaskResult> taskCallable, String taskParameter){ this.taskCallable = taskCallable; this.taskParameter = taskParameter; } @Override public void run() { //TODO 一系列业务逻辑,将结果数据封装成TaskResult对象并返回 TaskResult result = new TaskResult(); result.setTaskStatus(1); result.setTaskMessage(this.taskParameter); result.setTaskResult("异步回调成功"); taskCallable.callable(result); }}到这里,整个大的框架算是完成了,接下来,就是测试看能否获取到异步任务的结果了。
- 异步任务测试类
package io.binghe.concurrent.lab04;/** * @author binghe * @version 1.0.0 * @description 测试回调 */public class TaskCallableTest { public static void main(String[] args){ TaskCallable<TaskResult> taskCallable = new TaskHandler(); TaskExecutor taskExecutor = new TaskExecutor(taskCallable, "测试回调任务"); new Thread(taskExecutor).start(); }}在测试类中,使用Thread类创建一个新的线程,并启动线程运行任务。运行程序最终的接口数据如下所示。
TaskResult{taskStatus=1, taskMessage='测试回调任务', taskResult='异步回调成功'}大家可以细细品味下这种获取异步结果的方式。这里,只是简单的使用了Thread类来创建并启动线程,也可以使用线程池的方式实现。大家可自行实现以线程池的方式通过回调接口获取异步结果。
2.有返回结果的异步模型
尽管使用回调接口能够获取异步任务的结果,但是这种方式使用起来略显复杂。在JDK中提供了可以直接返回异步结果的处理方案。最常用的就是使用Future接口或者其实现类FutureTask来接收任务的返回结果。
- 使用Future接口获取异步结果
使用Future接口往往配合线程池来获取异步执行结果,如下所示。
package io.binghe.concurrent.lab04;import java.util.concurrent.*;/** * @author binghe * @version 1.0.0 * @description 测试Future获取异步结果 */public class FutureTest { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executorService = Executors.newSingleThreadExecutor(); Future<String> future = executorService.submit(new Callable<String>() { @Override public String call() throws Exception { return "测试Future获取异步结果"; } }); System.out.println(future.get()); executorService.shutdown(); }}运行结果如下所示。
测试Future获取异步结果- 使用FutureTask类获取异步结果
FutureTask类既可以结合Thread类使用也可以结合线程池使用,接下来,就看下这两种使用方式。
结合Thread类的使用示例如下所示。
package io.binghe.concurrent.lab04;import java.util.concurrent.*;/** * @author binghe * @version 1.0.0 * @description 测试FutureTask获取异步结果 */public class FutureTaskTest { public static void main(String[] args)throws ExecutionException, InterruptedException{ FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() { @Override public String call() throws Exception { return "测试FutureTask获取异步结果"; } }); new Thread(futureTask).start(); System.out.println(futureTask.get()); }}运行结果如下所示。
测试FutureTask获取异步结果结合线程池的使用示例如下。
package io.binghe.concurrent.lab04;import java.util.concurrent.*;/** * @author binghe * @version 1.0.0 * @description 测试FutureTask获取异步结果 */public class FutureTaskTest { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executorService = Executors.newSingleThreadExecutor(); FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() { @Override public String call() throws Exception { return "测试FutureTask获取异步结果"; } }); executorService.execute(futureTask); System.out.println(futureTask.get()); executorService.shutdown(); }}运行结果如下所示。
测试FutureTask获取异步结果可以看到使用Future接口或者FutureTask类来获取异步结果比使用回调接口获取异步结果简单多了。注意:实现异步的方式很多,这里只是用多线程举例。
接下来,就深入分析下Future接口。
边栏推荐
- Qt学习15 用户界面与业务逻辑的分离
- Lizuofan, co-founder of nonconvex: Taking quantification as his lifelong career
- Qt学习05 Qt Creator工程介绍
- Opencv4.0 installation of raspberry pie for Xiaobai
- Week 12 experiment -- implementation of VGA protocol based on FPGA
- Is it safe to open a stock account online
- 【每日3题(3)】重新格式化电话号码
- The Chinese Computational Linguistics Conference and the national knowledge atlas and Semantic Computing Conference are in full swing
- 适合小白的树莓派opencv4.0安装
- Limit introduction summary
猜你喜欢

中国计算语言学大会、全国知识图谱与语义计算大会赛题火热进行中

Nature | 全球海洋微生物组的生物合成潜力

Self-Improvement! Junior college "counter attack" master of Zhejiang University, 3 SCI, and finally become a doctor of Tsinghua University!

Data analysis method and Thinking: funnel analysis
![Leetcode 535 encryption and decryption of tinyurl [map] the leetcode road of heroding](/img/76/709bbbbd8eb01f32683a96c4abddb9.png)
Leetcode 535 encryption and decryption of tinyurl [map] the leetcode road of heroding

如何识别出轮廓准确的长和宽

Xuetong denies that the theft of QQ number is related to it: it has been reported; IPhone 14 is ready for mass production: four models are launched simultaneously; Simple and elegant software has long

The first "cyborg" in the world died, and he only transformed himself to "change his life against the sky"

什么?漫画居然能免费看全本了,这还不学起来一起做省钱小能手
![[NLP] text generation topic 1: basic knowledge](/img/cf/2e29e55344ea4cc8ce48777878b867.png)
[NLP] text generation topic 1: basic knowledge
随机推荐
Uber前安全主管面临欺诈指控 曾隐瞒数据泄露事件
Creating postgre enterprise database by ArcGIS
【HBZ分享】Semaphore 与 CountDownLatch原理
Cornerstone of efficient remote office: effective communication | community essay solicitation
【每日3题(1)】判断国际象棋棋盘中一个格子的颜色
(JS) isnan() method determines the reason why undefined is true
Online text filter less than specified length tool
极限导论总结
How to find out the wrong mobile number when querying MySQL
新版CorelDRAW Technical Suite2022最新详细功能介绍
Ikvm Net project progress
Nature | 全球海洋微生物组的生物合成潜力
如何识别出轮廓准确的长和宽
云原生开发必备:首个通用无代码开发平台 iVX 编辑器
软件工程导论——第五章——总体设计
Multi thread communication between client and server (primary version)
面试高并发,凉了!!(全程高能,建议收藏)
MySQL 索引失效的几种类型以及解决方式
misc3~7
Babbitt | yuancosmos daily must read: HTC announced the launch of the first yuancosmos mobile phone, which costs about 2700 yuan. What are the new ways to play