Java使用FutureTask实现预加载的示例详解
FutureTask介绍
FutureTask也可以用作闭锁;FutureTask的计算是通过Callable来实现的,相当于一种可生成结果的Runnable,并且可以处于3种状态,分别是等待运行(waiting to run)
、正在运行(Running)
、和运行完成(Completed)
,而运行完成
表示计算的所有可能结束方式,包括正常结束
,由于取消而结束
和由于异常而结束
等,当FutureTask进入完成状态后,它就会永远停止在这个状态上。我们可以使用Future.get()
方法获取任务执行的状态。
使用场景
Future.get的行为取决于任务的状态,如果任务已经完成,那么get会立即返回结果,否则get方法将阻塞直到任务进入完成状态,然后返回结果或者抛出异常,FutureTask将计算结果从执行计算的线程传递到获取这个结果的线程,而FutureTask的规范确保了这种传递过程能实现结果的正确性
基于FutureTask的特性,通常可以使用FutureTask做一些预加载工作,比如一些时间较长的计算,这些计算可以在使用计算结果之前启动,并且计算的结果将在稍后是同,通过提前启动计算,可以减少等待结果时需要的时间
实例解析
假设我们要加载一个产品信息,使用FutureTask来执行一个高开销的计算。代码如下所示: 首先简单写一个产品的Bean类:
static class ProductInfo { public ProductInfo(String name, String order_id) { this.name = name; this.order_id = order_id; } private String name; private String order_id; @Override public String toString() { return "ProductInfo{" + "name='" + name + '\'' + ", order_id='" + order_id + '\'' + '}'; } }
然后使用FutureTask实现一个产品信息预加载功能:
static class Preloader { public void start() { thread.start(); } private final FutureTask<ProductInfo> futureTask = new FutureTask<>(new Callable<ProductInfo>() { @Override public ProductInfo call() throws Exception { return loadProductInfo(); } }); public ProductInfo get() throws ExecutionException, InterruptedException { return futureTask.get(); } private final Thread thread = new Thread(futureTask); private ProductInfo loadProductInfo() { try { Thread.sleep(5000); } catch (InterruptedException e) { throw new RuntimeException(e); } return new ProductInfo("衣服", "9527"); } }
验证代码:
Preloader preloader = new Preloader(); preloader.start(); System.out.println("start get product info before" + System.currentTimeMillis() / 1000); ProductInfo productInfo = null; try { productInfo = preloader.get(); } catch (ExecutionException | InterruptedException e) { throw new RuntimeException(e); } System.out.println("start get product info afte" +System.currentTimeMillis() / 1000); System.out.println("productInfo: " + productInfo);
如上面的代码所示:Preloader
创建了一个FutureTask,其中包含了加载产品信息的任务,以及一个执行运算的线程。我们增加了一个 Thread.sleep(5000);
模拟加载耗时。由于在构造函数或者静态初始化方法中启动线程不是一种好方法,所以提供了一个start方法来启动线程,当程序后面需要ProductInfo
结果时,可以调用Preloader
提供的get
方法,如果数据已经加载,那么会返回这些数据,否则将等待加载完成后再返回。
到此这篇关于Java使用FutureTask实现预加载的示例详解的文章就介绍到这了,更多相关Java FutureTask预加载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Java使用Statement接口执行SQL语句操作实例分析
这篇文章主要介绍了Java使用Statement接口执行SQL语句操作,结合实例形式详细分析了Java使用Statement接口针对mysql数据库进行连接与执行SQL语句增删改查等相关操作技巧与注意事项,需要的朋友可以参考下2018-07-07
最新评论