以两种异步模型应用案例,深度解析Future接口

发布时间:2021-07-31 23:47 来源:https://blog.51cto.com/u_15214 阅读:199 作者:华为云开发者社区 栏目: 云计算

本文以实际案例的形式分析了两种异步模型,并从源码角度深度解析Future接口和FutureTask类,希望大家踏下心来,打开你的IDE,跟着文章看源码,相信你一定收获不小!

一、两种异步模型

在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 + 'http://blog.51cto.com/u_15214399/3230109/\'' + ", taskResult='" + taskResult + 'http://blog.51cto.com/u_15214399/3230109/\'' + '}'; } }

创建回调接口的实现类

回调接口的实现类主要用来对任务的返回结果进行相应的业务处理,这里,为了方便演示,只是将结果数据返回。大家需要根据具体的业务场景来做相应的分析和处理。

package io.binghe.concurrent.lab04; /** * @author binghe * @version 1.0.0 * @description 回调函数的实现类 */ public class TaskHandler implements TaskCallable<TaskResult> { @Override public 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接口获取异步结果

免责声明:本站发布的内容(图片、视频和文字)以原创、来自互联网转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:ts@56dr.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。