Java 并发专题 :FutureTask 实现预加载数据 在线看电子书、浏览器浏览网页等
继续并发专题~
FutureTask 有点类似Runnable,都可以通过Thread来启动,不过FutureTask可以返回执行完毕的数据,并且FutureTask的get方法支持阻塞。
由于:FutureTask可以返回执行完毕的数据,并且FutureTask的get方法支持阻塞这两个特性,我们可以用来预先加载一些可能用到资源,然后要用的时候,调用get方法获取(如果资源加载完,直接返回;否则继续等待其加载完成)。
下面通过两个例子来介绍下:
1、使用FutureTask来预加载稍后要用的的数据。
package com.zhy.concurrency.futuretask; import <a href="http://lib.csdn.net/base/17" class="replace_word" title="Java EE知识库" target="_blank" style="color:#df3434; font-weight:bold;">java</a>.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask; /**
* 使用FutureTask来提前加载稍后要用到的数据
*
* @author zhy
*
*/
public class PreLoaderUseFutureTask
{
/**
* 创建一个FutureTask用来加载资源
*/
private final FutureTask<String> futureTask = new FutureTask<String>(
new Callable<String>()
{
@Override
public String call() throws Exception
{
Thread.sleep();
return "加载资源需要3秒";
}
}); public final Thread thread = new Thread(futureTask); public void start()
{
thread.start();
} /**
* 获取资源
*
* @return
* @throws ExecutionException
* @throws InterruptedException
*/
public String getRes() throws InterruptedException, ExecutionException
{
return futureTask.get();//加载完毕直接返回,否则等待加载完毕 } public static void main(String[] args) throws InterruptedException, ExecutionException
{ PreLoaderUseFutureTask task = new PreLoaderUseFutureTask();
/**
* 开启预加载资源
*/
task.start();
// 用户在真正需要加载资源前进行了其他操作了2秒
Thread.sleep(); /**
* 获取资源
*/
System.out.println(System.currentTimeMillis() + ":开始加载资源");
String res = task.getRes();
System.out.println(res);
System.out.println(System.currentTimeMillis() + ":加载资源结束");
} }
运行结果:
:开始加载资源
加载资源需要3秒
:加载资源结束
可以看到,本来加载资源的时间需要3秒,现在只花费了1秒,如果用户其他操作时间更长,则可直接返回,极大增加了用户体验。
2、看下Future的API
可以看到Future的API,还是比简单的,见名知意的感觉,get( long , TimeUnit )还能支持,设置最大等待时间,比如某个操作耗时太长,就可以取消了。
3、FutureTask模拟,用户在线观看电子书的预加载功能
用户观看当前页时,后台预先把下一页加载好,这样可以大幅度提高用户的体验,不需要每一页都等待加载,用户会觉得此电子书软件很流畅,哈哈,用户觉得好,才是真的好。
package com.zhy.concurrency.futuretask; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask; /**
* 使用FutureTask模拟预加载下一页图书的内容
*
* @author zhy
*
*/
public class BookInstance
{ /**
* 当前的页码
*/
private volatile int currentPage = ; /**
* 异步的任务获取当前页的内容
*/
FutureTask<String> futureTask = new FutureTask<String>(
new Callable<String>()
{
@Override
public String call() throws Exception
{
return loadDataFromNet();
}
}); /**
* 实例化一本书,并传入当前读到的页码
*
* @param currentPage
*/
public BookInstance(int currentPage)
{
this.currentPage = currentPage;
/**
* 直接启动线程获取当前页码内容
*/
Thread thread = new Thread(futureTask);
thread.start();
} /**
* 获取当前页的内容
*
* @return
* @throws InterruptedException
* @throws ExecutionException
*/
public String getCurrentPageContent() throws InterruptedException,
ExecutionException
{
String con = futureTask.get();
this.currentPage = currentPage + ;
Thread thread = new Thread(futureTask = new FutureTask<String>(
new Callable<String>()
{
@Override
public String call() throws Exception
{
return loadDataFromNet();
}
}));
thread.start();
return con;
} /**
* 根据页码从网络抓取数据
*
* @return
* @throws InterruptedException
*/
private String loadDataFromNet() throws InterruptedException
{
Thread.sleep();
return "Page " + this.currentPage + " : the content ...."; } public static void main(String[] args) throws InterruptedException,
ExecutionException
{
BookInstance instance = new BookInstance();
for (int i = ; i < ; i++)
{
long start = System.currentTimeMillis();
String content = instance.getCurrentPageContent();
System.out.println("[1秒阅读时间]read:" + content);
Thread.sleep();
System.out.println(System.currentTimeMillis() - start);
} }
}
package com.zhy.concurrency.futuretask; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask; /**
* 使用FutureTask模拟预加载下一页图书的内容
*
* @author zhy
*
*/
public class BookInstance
{ /**
* 当前的页码
*/
private volatile int currentPage = ; /**
* 异步的任务获取当前页的内容
*/
FutureTask<String> futureTask = new FutureTask<String>(
new Callable<String>()
{
@Override
public String call() throws Exception
{
return loadDataFromNet();
}
}); /**
* 实例化一本书,并传入当前读到的页码
*
* @param currentPage
*/
public BookInstance(int currentPage)
{
this.currentPage = currentPage;
/**
* 直接启动线程获取当前页码内容
*/
Thread thread = new Thread(futureTask);
thread.start();
} /**
* 获取当前页的内容
*
* @return
* @throws InterruptedException
* @throws ExecutionException
*/
public String getCurrentPageContent() throws InterruptedException,
ExecutionException
{
String con = futureTask.get();
this.currentPage = currentPage + ;
Thread thread = new Thread(futureTask = new FutureTask<String>(
new Callable<String>()
{
@Override
public String call() throws Exception
{
return loadDataFromNet();
}
}));
thread.start();
return con;
} /**
* 根据页码从网络抓取数据
*
* @return
* @throws InterruptedException
*/
private String loadDataFromNet() throws InterruptedException
{
Thread.sleep();
return "Page " + this.currentPage + " : the content ...."; } public static void main(String[] args) throws InterruptedException,
ExecutionException
{
BookInstance instance = new BookInstance();
for (int i = ; i < ; i++)
{
long start = System.currentTimeMillis();
String content = instance.getCurrentPageContent();
System.out.println("[1秒阅读时间]read:" + content);
Thread.sleep();
System.out.println(System.currentTimeMillis() - start);
} }
}
输出结果:
[1秒阅读时间]read:Page : the content .... [1秒阅读时间]read:Page : the content .... [1秒阅读时间]read:Page : the content .... [1秒阅读时间]read:Page : the content .... [1秒阅读时间]read:Page : the content ....
可以看到,除了第一次观看当前页需要等待网络加载数据的过程(输出的:2001,1000是加载耗时,1000是用户阅读时间),接下来的页面都是瞬间返回(输出的1000是用户阅读时间),完全不需要等待。
代码都是为了讲解FutureTask的应用场景,,,请勿直接在项目中使用。
好了,就到这里,欢迎各位留言。
Java 并发专题 :FutureTask 实现预加载数据 在线看电子书、浏览器浏览网页等的更多相关文章
- 基于spring的web项目启动时预加载数据到ServletContext
1.要在web启动时预加载数据到ServletContext,实现方法有很多,一种比较简单的方案就是: 1)新建一个bean,定义其初始化方法: <bean id="beanId&qu ...
- 巧力避免ViewPager的预加载数据,Tablayout+Fragment+viewPager
问题描述 最近在进行一个项目的开发,其中使用到了Tablayout+Fragment+viewPager来搭建一个基本的框架,从而出现了设置数据适配器的时候,item的位置错乱问题.我打印log日志的 ...
- CommandLineRunner预加载数据
在使用SpringBoot构建项目时,我们通常有一些预先数据的加载.那么SpringBoot提供了一个简单的方式来实现–CommandLineRunner. CommandLineRunner是一个接 ...
- java攻城狮之路(Android篇)--widget_webview_metadata_popupwindow_tabhost_分页加载数据_菜单
一.widget:桌面小控件1 写一个类extends AppWidgetProvider 2 在清单文件件中注册: <receiver android:name=".ExampleA ...
- js中的预加载与懒加载(延迟加载)
js中加载分两种:预加载与延迟加载 一. 预加载,增强用户的体验,但会加载服务器的负担.一般会使用多种 CSS(background).JS(Image).HTML(<img />) . ...
- MailOtto 实现完美预加载以及源码解读
背景: 最近项目组需要一个小课题分享,小白刚好从微博里看到一个这样有趣的开源工具MailOtto,是阿里巴巴员工 Drakeet 维护的一个专注懒事件的事件总线,gitHub地址为:https://g ...
- web前端图片预加载
是什么? 浏览器会缓存静态资源(hmtl/css/img等).图片预加载就是让浏览器提前缓存图片,提升用户体验. 浏览器什么情况下会下载图片? 1,解析到html中img的src属性的时候 2,解析到 ...
- html预加载之link标签
我们之前提及过link rel 里面有preload和prefetch.modulepreload,都是用于预加载资源 <link rel="preload" href=&q ...
- Gorm 预加载及输出处理(二)- 查询输出处理
上一篇<Gorm 预加载及输出处理(一)- 预加载应用>中留下的三个问题: 如何自定义输出结构,只输出指定字段? 如何自定义字段名,并去掉空值字段? 如何自定义时间格式? 这一篇先解决前两 ...
随机推荐
- webService设置超时时间
在客户端配置文件中设置: <bindings> <basicHttpBinding> <binding name="UrlCrawler ...
- ubuntu 12.04(Precise Pangolin)启用休眠(Hibernate)功能的方案
官方支持文档:https://help.ubuntu.com/12.04/ubuntu-help/power-hibernate.html 按照这篇官方支持,因为休眠功能存在bug,12.04没有默认 ...
- MongoDBAuth
1,mogoDB 认证登陆
- iOS 删除相册中照片--来自简书
来自:http://www.jianshu.com/p/ac18aa3f28c2 最近公司的app有一个新功能是在app中删除相册的照片 ,本来是一个比较简单地功能,在做的过程中却发现AssetsLi ...
- 谷歌Cartographer学习(1)-快速安装测试(转载)
转载自谷歌Cartographer学习(1)-快速安装测试 代码放到个人github上,https://github.com/hitcm/ 如下,需要安装3个软件包,ceres solver.cart ...
- 蚂蚁的难题(二)首尾相连数组的最大子数组和(DP)
蚂蚁的难题(二) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 下雨了,下雨了,蚂蚁搬家了. 已知有n种食材需要搬走,这些食材从1到n依次排成了一个圈.小蚂蚁对每种食材 ...
- Android系统的开机画面显示过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7691321 好几个月都没有更新过博客了,从今天 ...
- Linux 下的 Nginx 反向代理配置.
最近实践中遇到了需要利用 nginx 进行反向代理服务器请求的需求,以前没怎么碰触过,因此花了1个多小时,快速阅览了一下nginx官网在反向代理服务中给出的基本定义: 说实话,官网给予的定义是精准的, ...
- Java - 泛型 ( Generic )
Java - 泛型 ( Generic ) > 泛型的特点 > 解决元素存储的安全性问题 > 解决获取数据元素时,需要类型强转的问题 ...
- 简单随笔——如何在gridview的页脚显示信息。。。。
我是超级大菜鸟...哈哈 先上图看看是不是你需要的 第一步,右击gridview,在事件中,单击RowdataBond事件. 在这之前一定要记得在gridview属性中的ShowFooter设置为“t ...