继续并发专题~

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 实现预加载数据 在线看电子书、浏览器浏览网页等的更多相关文章

  1. 基于spring的web项目启动时预加载数据到ServletContext

    1.要在web启动时预加载数据到ServletContext,实现方法有很多,一种比较简单的方案就是: 1)新建一个bean,定义其初始化方法: <bean id="beanId&qu ...

  2. 巧力避免ViewPager的预加载数据,Tablayout+Fragment+viewPager

    问题描述 最近在进行一个项目的开发,其中使用到了Tablayout+Fragment+viewPager来搭建一个基本的框架,从而出现了设置数据适配器的时候,item的位置错乱问题.我打印log日志的 ...

  3. CommandLineRunner预加载数据

    在使用SpringBoot构建项目时,我们通常有一些预先数据的加载.那么SpringBoot提供了一个简单的方式来实现–CommandLineRunner. CommandLineRunner是一个接 ...

  4. java攻城狮之路(Android篇)--widget_webview_metadata_popupwindow_tabhost_分页加载数据_菜单

    一.widget:桌面小控件1 写一个类extends AppWidgetProvider 2 在清单文件件中注册: <receiver android:name=".ExampleA ...

  5. js中的预加载与懒加载(延迟加载)

    js中加载分两种:预加载与延迟加载 一.  预加载,增强用户的体验,但会加载服务器的负担.一般会使用多种 CSS(background).JS(Image).HTML(<img />) . ...

  6. MailOtto 实现完美预加载以及源码解读

    背景: 最近项目组需要一个小课题分享,小白刚好从微博里看到一个这样有趣的开源工具MailOtto,是阿里巴巴员工 Drakeet 维护的一个专注懒事件的事件总线,gitHub地址为:https://g ...

  7. web前端图片预加载

    是什么? 浏览器会缓存静态资源(hmtl/css/img等).图片预加载就是让浏览器提前缓存图片,提升用户体验. 浏览器什么情况下会下载图片? 1,解析到html中img的src属性的时候 2,解析到 ...

  8. html预加载之link标签

    我们之前提及过link rel 里面有preload和prefetch.modulepreload,都是用于预加载资源 <link rel="preload" href=&q ...

  9. Gorm 预加载及输出处理(二)- 查询输出处理

    上一篇<Gorm 预加载及输出处理(一)- 预加载应用>中留下的三个问题: 如何自定义输出结构,只输出指定字段? 如何自定义字段名,并去掉空值字段? 如何自定义时间格式? 这一篇先解决前两 ...

随机推荐

  1. 【Xamarin挖墙脚系列:Xamarin.IOS的多个Storybord分隔视图的导航】

    在实际开发中,我是推荐使用画板Storybord的.也可以适当的添加xib进行界面的绘制.尽量不要用或者少用代码绘制视图.(少一些装B分子,可以极大的缩短项目的周期). 不要讲性能,不是不讲性能,ap ...

  2. icmp的报文,Destination Host Unreachable

    icmp的报文,Destination Host Unreachable的意思如下: http://www.corenetworkz.com/2009/05/destination-host-unre ...

  3. app行业发展趋势

    近日,移动开放平台发布了2014年第一季度App开发行业报告.报告中对目前国内app开发者的分布情况,个人开发者和企业开发者的开发领域,相应比例以及提交应用过程中出现的问题做出统计,为如何建立一个更好 ...

  4. UESTC_方老师买表 CDOJ 885

    老师买表 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Stat ...

  5. Windows多线程同步系列之三-----事件对象

    事件是一个内核事件,内核事件是什么呢,我理解也不深入也不好说,暂且理解为一个内核维护的数据类型吧通过内核事件同步主要 的方法是对事件的信号有和无来进行同步. 比如当我们一个线程进入一段临界代码(独占代 ...

  6. 正则表达式、find、grep、awk、sed

    1.正则表达式    (1)正则表达式一般用来描述文本模式的特殊用法,由普通字符(例如字符a-z)以及特殊字符(称为元字符,如/.*.?等)组成.   (2)基本元字符集及其含义       ^ :只 ...

  7. Unity 关于属性的get/set

    学习Unity的可能多数是C#转过来的, 一进来的时候你会发现Unity编写代码,在一些视频或文章中.基本都没有用过get/set使用, 多数是public string name;这样写的公开字段, ...

  8. category和extensions

    catgory 允许你为一个已经存在的类增加方法,而不需要增加一个子类.而且不需要知道它内部具体的实现. 另外,虽然Category不能够为类添加新的成员变量,但是Category包含类的所有成员变量 ...

  9. android面试题集1

    Android 面试题(有详细答案) 附带答案,共100分 一.选择题(30题,每题1.5分,共45分) 1.java.io包中定义了多个流类型来实现输入和输出功能,可以从不同的角度对其进行分类,按功 ...

  10. Java学习笔记50:JSONObject与JSONArray的使用

    Java不像PHP解析和生产JSON总是一个比较痛苦的过程.但是使用JSONObject和JSONArray会让整个过程相对舒服一些. 需要依赖的包:commons-lang.jar commons- ...