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

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

继续并发专题~

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

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

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

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

[java] view
plain
copy

  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
plain
copy

  1. 1400902789275:开始加载资源  
  2. 加载资源需要3秒  
  3. 1400902790275:加载资源结束  

可以看到,本来加载资源的时间需要3秒,现在只花费了1秒,如果用户其他操作时间更长,则可直接返回,极大增加了用户体验。

2、看下Future的API

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

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

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

[java] view
plain
copy

  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
plain
copy

  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是用户阅读时间),完全不需要等待。

时间: 2024-09-28 23:23:03

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

预加载css或javascript的js代码_javascript技巧

预加载文件一般有两种常用的方式:xhr和动态插入节点的方式.动态插入节点是最为简单也最为广泛的一种异步加载方式(例如yui的Get模块),然后使用动态插入节点方法加载的文件都会在加载后立即执行,javascript的执行一方面会占用浏览器js执行进程,另一方面也可能改变页面结构,而css的执行更有可能让整个页面变化.xhr方式虽然不会执行脚本,但是由于同域的限制,且如今网站的静态文件都是部署在cdn服务器上,如何预加载css js文件也变有点玄妙了. Stoyan Stefanov 撰文简明的阐

懒加载和预加载的实现

提到前端性能优化中图片资源的优化,懒加载和预加载就不能不说,下面我用最简洁明了的语言说明懒加载和预加载的核心要点以及实现 懒加载 什么是懒加载 懒加载也就是延迟加载;当访问一个页面时,先将img标签中的src链接设为同一张图片(这样就只需请求一次,俗称占位图),将其真正的图片地址存储在img标签的自定义属性中(比如data-src);当js监听到该图片元素进入可视窗口时,即将自定义属性中的地址存储到src属性中,达到懒加载的效果;这样做能防止页面一次性向服务器响应大量请求导致服务器响应慢页面卡顿

ViewPager+Fragment取消预加载(延迟加载)

在项目中,都或多或少地使用的Tab布局,所以大都会用到ViewPager+Fragment,但是Fragment有个不好或者太好的地方. 例如你在ViewPager中添加了三个Fragment,当加载ViewPager中第一个Fragment时,它会默认帮你预先加载了第二个Fragment,当你加载第二个Fragment时,它会帮你加载第三个Fragment. 这样虽然有时很好,但是用户只需看一个Fragment时,我们就做了一些多余工作加载了第二个Fragment.在这只需要取消Fragmen

解析javascript图片懒加载与预加载的分析总结_javascript技巧

本篇文章主要介绍了懒加载和预加载两种技术的解析,废话不多说,一起来看吧. 懒加载也叫延迟加载:前一篇文章有介绍:JS图片延迟加载 延迟加载图片或符合某些条件时才加载某些图片. 预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染. 两种技术的本质:两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载.懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力. 懒加载的意义及实现方式有: 意义: 懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数. 实现方式:

完美解决关于禁止ViewPager预加载的相关问题

我最近上班又遇到一个小难题了,就是如题所述:ViewPager预加载的问题.相信用过ViewPager的人大抵都有遇到过这种情况,网上的解决办法也就那么几个,终于在我自己不断试验之下,完美解决了(禁止了)ViewPager的预加载. 好了,首先来说明一下,什么是ViewPager的预加载:ViewPager有一个 "预加载"的机制,默认会把ViewPager当前位置的左右相邻页面预先初始化(俗称的预加载),它的默认值是 1,这样做的好处就是ViewPager左右滑动会更加流畅. 可是我

jQuery简单实现图片预加载

    jQuery实现图片预加载:   我们在做网站的时候经常会遇到这样的问题:一个页面有大量的图片导致页面加载速度缓慢,经常会出现一个白页用户体验很不好.那么如何解决这个问题呢?下面我来介绍一种在实际应用中经常会使用到的js预加载的方法. JS代码 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 $(function(){ loadImg("fd039245d688d43f14f69eff7f1ed21b0ef43b5b.gif",ad

性能优化总结(六):预加载、聚合SQL应用实例

   前面已经把原理都讲了一遍,这篇主要是给出一个应用的实例.该实例取自GIX4,比较复杂. 领域模型:     领域模型间的关系,如下: 右边模型链的具体关系在<第二篇>中已经描述过,不再赘述. 本次重点在于红线框住部分: Project:表示一个建设项目: ProjectPBS:一个项目下包含的很多PBS: PBSPropertyValue:一个PBS我们可以为它设置多个值,每一个值对应一个PBSType(模板)中已定义的属性,值的范围也是只能在属性中已定义的可选值中进行选择. 对应的UI

javascript图片懒加载与预加载的分析

   预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染.  两种技术的本质:两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载.懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力.  懒加载的意义及实现方式有:    意义: 懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数.    实现方式:       1.第一种是纯粹的延迟加载,使用setTimeOut或setInterval进行加载延迟.     2.第二种是条件加载,符合某些条件,或触发

如何通过预加载器提升网页加载速度

预加载器(Pre-loader)可以说是提高浏览器性能最重要的举措.Mozilla 官方发布数据,通过预加载器技术网页的加载性能提升了19%,Chrome测试了 Alexa 排名前2000名网站,性能有20%的提升. 它并不是一门新技术,有人认为只有 Chrome 才具备这个功能.也有人认为它是有史以来提升浏览器性能最有效的方法.如果你第一次接触预加载器,也许心中已经有了无数个问号.什么是预加载器?它是如何提升浏览器性能的? 首先需要了解浏览器是如何加载网页的 一个网页的加载依赖于脚本文件.CS