Java 并发专题 :FutureTask 实现预加载数据 在线看电子书、浏览器浏览网页等-阿里云开发者社区

开发者社区> 恩恩123> 正文

Java 并发专题 :FutureTask 实现预加载数据 在线看电子书、浏览器浏览网页等

简介: 转自:http://blog.csdn.net/lmj623565791/article/details/26817403  继续并发专题~ FutureTask 有点类似Runnable,都可以通过Thread来启动,不过FutureTask可以返回执行完毕的数据,并且FutureTask的get方法支持阻塞。 由于:FutureTask可以返回执行完毕的数据,
+关注继续查看

转自:http://blog.csdn.net/lmj623565791/article/details/26817403 


继续并发专题~

FutureTask 有点类似Runnable,都可以通过Thread来启动,不过FutureTask可以返回执行完毕的数据,并且FutureTask的get方法支持阻塞。

由于:FutureTask可以返回执行完毕的数据,并且FutureTask的get方法支持阻塞这两个特性,我们可以用来预先加载一些可能用到资源,然后要用的时候,调用get方法获取(如果资源加载完,直接返回;否则继续等待其加载完成)。

下面通过两个例子来介绍下:

1、使用FutureTask来预加载稍后要用的的数据。

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.zhy.concurrency.futuretask;  
  2.   
  3. import java.util.concurrent.Callable;  
  4. import java.util.concurrent.ExecutionException;  
  5. import java.util.concurrent.FutureTask;  
  6.   
  7. /** 
  8.  * 使用FutureTask来提前加载稍后要用到的数据 
  9.  *  
  10.  * @author zhy 
  11.  *  
  12.  */  
  13. public class PreLoaderUseFutureTask  
  14. {  
  15.     /** 
  16.      * 创建一个FutureTask用来加载资源 
  17.      */  
  18.     private final FutureTask<String> futureTask = new FutureTask<String>(  
  19.             new Callable<String>()  
  20.             {  
  21.                 @Override  
  22.                 public String call() throws Exception  
  23.                 {  
  24.                     Thread.sleep(3000);  
  25.                     return "加载资源需要3秒";  
  26.                 }  
  27.             });  
  28.   
  29.     public final Thread thread = new Thread(futureTask);  
  30.   
  31.     public void start()  
  32.     {  
  33.         thread.start();  
  34.     }  
  35.   
  36.     /** 
  37.      * 获取资源 
  38.      *  
  39.      * @return 
  40.      * @throws ExecutionException  
  41.      * @throws InterruptedException  
  42.      */  
  43.     public String getRes() throws InterruptedException, ExecutionException  
  44.     {  
  45.         return futureTask.get();//加载完毕直接返回,否则等待加载完毕  
  46.   
  47.     }  
  48.   
  49.     public static void main(String[] args) throws InterruptedException, ExecutionException  
  50.     {  
  51.   
  52.         PreLoaderUseFutureTask task = new PreLoaderUseFutureTask();  
  53.         /** 
  54.          * 开启预加载资源 
  55.          */  
  56.         task.start();  
  57.         // 用户在真正需要加载资源前进行了其他操作了2秒  
  58.         Thread.sleep(2000);  
  59.   
  60.         /** 
  61.          * 获取资源 
  62.          */  
  63.         System.out.println(System.currentTimeMillis() + ":开始加载资源");  
  64.         String res = task.getRes();  
  65.         System.out.println(res);  
  66.         System.out.println(System.currentTimeMillis() + ":加载资源结束");  
  67.     }  
  68.   
  69. }  

运行结果:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. 1400902789275:开始加载资源  
  2. 加载资源需要3秒  
  3. 1400902790275:加载资源结束  
可以看到,本来加载资源的时间需要3秒,现在只花费了1秒,如果用户其他操作时间更长,则可直接返回,极大增加了用户体验。

2、看下Future的API


可以看到Future的API,还是比简单的,见名知意的感觉,get( long , TimeUnit )还能支持,设置最大等待时间,比如某个操作耗时太长,就可以取消了。

3、FutureTask模拟,用户在线观看电子书的预加载功能

用户观看当前页时,后台预先把下一页加载好,这样可以大幅度提高用户的体验,不需要每一页都等待加载,用户会觉得此电子书软件很流畅,哈哈,用户觉得好,才是真的好。

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.zhy.concurrency.futuretask;  
  2.   
  3. import java.util.concurrent.Callable;  
  4. import java.util.concurrent.ExecutionException;  
  5. import java.util.concurrent.FutureTask;  
  6.   
  7.   
  8. /** 
  9.  * 使用FutureTask模拟预加载下一页图书的内容 
  10.  *  
  11.  * @author zhy 
  12.  *  
  13.  */  
  14. public class BookInstance  
  15. {  
  16.   
  17.     /** 
  18.      * 当前的页码 
  19.      */  
  20.     private volatile int currentPage = 1;  
  21.   
  22.     /** 
  23.      * 异步的任务获取当前页的内容 
  24.      */  
  25.     FutureTask<String> futureTask = new FutureTask<String>(  
  26.             new Callable<String>()  
  27.             {  
  28.                 @Override  
  29.                 public String call() throws Exception  
  30.                 {  
  31.                     return loadDataFromNet();  
  32.                 }  
  33.             });  
  34.   
  35.     /** 
  36.      * 实例化一本书,并传入当前读到的页码 
  37.      *  
  38.      * @param currentPage 
  39.      */  
  40.     public BookInstance(int currentPage)  
  41.     {  
  42.         this.currentPage = currentPage;  
  43.         /** 
  44.          * 直接启动线程获取当前页码内容 
  45.          */  
  46.         Thread thread = new Thread(futureTask);  
  47.         thread.start();  
  48.     }  
  49.   
  50.     /** 
  51.      * 获取当前页的内容 
  52.      *  
  53.      * @return 
  54.      * @throws InterruptedException 
  55.      * @throws ExecutionException 
  56.      */  
  57.     public String getCurrentPageContent() throws InterruptedException,  
  58.             ExecutionException  
  59.     {  
  60.         String con = futureTask.get();  
  61.         this.currentPage = currentPage + 1;  
  62.         Thread thread = new Thread(futureTask = new FutureTask<String>(  
  63.                 new Callable<String>()  
  64.                 {  
  65.                     @Override  
  66.                     public String call() throws Exception  
  67.                     {  
  68.                         return loadDataFromNet();  
  69.                     }  
  70.                 }));  
  71.         thread.start();  
  72.         return con;  
  73.     }  
  74.   
  75.     /** 
  76.      * 根据页码从网络抓取数据 
  77.      *  
  78.      * @return 
  79.      * @throws InterruptedException 
  80.      */  
  81.     private String loadDataFromNet() throws InterruptedException  
  82.     {  
  83.         Thread.sleep(1000);  
  84.         return "Page " + this.currentPage + " : the content ....";  
  85.   
  86.     }  
  87.   
  88.     public static void main(String[] args) throws InterruptedException,  
  89.             ExecutionException  
  90.     {  
  91.         BookInstance instance = new BookInstance(1);  
  92.         for (int i = 0; i < 10; i++)  
  93.         {  
  94.             long start = System.currentTimeMillis();  
  95.             String content = instance.getCurrentPageContent();  
  96.             System.out.println("[1秒阅读时间]read:" + content);  
  97.             Thread.sleep(1000);  
  98.             System.out.println(System.currentTimeMillis() - start);  
  99.         }  
  100.   
  101.     }  
  102. }  

输出结果:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. [1秒阅读时间]read:Page 1 : the content ....  
  2. 2001  
  3. [1秒阅读时间]read:Page 2 : the content ....  
  4. 1000  
  5. [1秒阅读时间]read:Page 3 : the content ....  
  6. 1001  
  7. [1秒阅读时间]read:Page 4 : the content ....  
  8. 1000  
  9. [1秒阅读时间]read:Page 5 : the content ....  
  10. 1001  

可以看到,除了第一次观看当前页需要等待网络加载数据的过程(输出的:2001,1000是加载耗时,1000是用户阅读时间),接下来的页面都是瞬间返回(输出的1000是用户阅读时间),完全不需要等待。


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
hbase源码系列(四)数据模型-表定义和列族定义的具体含义
hbase是一个KeyValue型的数据库,在《hbase实战》描述它的逻辑模型【行键,列族,列限定符,时间版本】,物理模型是基于列族的。但实际情况是啥?还是上点代码吧。
2489 0
《HTML CSS JavaScript 网页制作从入门到精通 第3版》—— 导读
十多年前,Internet在国内开始流行。其中,网页作为互联网的主要媒介受到了电脑爱好者的广泛关注。由于当时网速的限制,网页主要承载文本、图片等简单数据,使用Dreamweaver或Frontpage软件即可轻松制作网页。
1185 0
DalekJS – 基于 JavaScript 实现跨浏览器的自动化测试
  在 Web 项目中,浏览器兼容以及跨浏览器测试是最重要的也是最费劲的工作。DalekJS 是一个基于 JavaScript(或 Node.js) 的免费和开源的自动化测试接口。它能够同时运行测试一组流行的浏览器(Chrome,IE,Firefox 和 WebKit)。
637 0
数据分页时每页首条记录索引如何计算
现在有8条数据,数据库中第一条索引是0,也就是每条数据的索引分别是0,1,2,3,4,5,6,7 。 现在要求每页是2条也就是pagesize = 2,当前页为currentPage。   模拟分页:0 1 | 2 3 | 4 5 | 6 7 第1页currentPage = 1,pagesize = 2,首条记录索引为0,(1 - 1) * 2 第2页currentPage =
899 0
Socket.IO – 基于 WebSocket 构建跨浏览器的实时应用
   Socket.IO 是一个功能非常强大的框架,能够帮助你构建基于 WebSocket 的跨浏览器的实时应用。支持主流浏览器,多种平台,多种传输模式,还可以集合 Exppress 框架构建各种功能复杂的实时应用。
804 0
判断当面的网页加载完成
if(document.readyState=='complete'){ window.alert('加载完成!');} ...
507 0
数据天生就是流式的
现在依然很多人使用Azkaban/Oozie等工具衔接各个系统,通过外力让数据进行流转。而随着流式计算慢慢成熟与稳定,数据必然如河水一般,天生就是流式的。
1771 0
+关注
76
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载