继续并发专题~

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. ckeditor详解

    源网页编辑软件FCKEditor在09年发布更新到3.0,并改名为CKEditor.改进后的ckeditor更加模块话,配置更加灵活,和以前的fckeditor使用方式上也有所不同.在我的mvc项目中 ...

  2. 十四、职责链(Chain of Responsibility)模式--行为型模式(Behavioral Pattern)

    职责链模式是一种对象的行为模式[GOF95].在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知 ...

  3. Qt直接使用OpenSSL里的函数

    简述 OpenSSL是一个强大的安全套接字层密码库,囊括主要的密码算法.常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用. 简述 下载安装 使用 更多参考 下载安装 ...

  4. MIT-scheme安装

    下载地址: http://www.gnu.org/software/mit-scheme/ 下载windows版本,安装. The MIT-Scheme can be installed by jus ...

  5. JAVA的类加载器,详细解释

    JVM规范定义了两种类型的类装载器:启动内装载器(bootstrap)和用户自定义装载器(user-defined class loader). 一. ClassLoader基本概念 1.ClassL ...

  6. Linux系统编程(5)——文件与IO之mmap函数

    mmap系统调用它本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样对普通文件的操作.而Posix或系统V的共享内存IPC则纯粹用于共享目的,mmap()实现共享内存也是其主要应用之一. ...

  7. Kth Largest Element in an Array 解答

    Question Find the kth largest element in an unsorted array. Note that it is the kth largest element ...

  8. char与byte的差别

    非常多刚開始学习的人(包含我,已经学了一年多java了)肯会对char和byte这两种数据类型有所疑惑,相互混淆,今天特地查了好多资料,对byte和char两种数据类型进行了总结和比較,先将结果与大家 ...

  9. C++实现20个设计模式

    http://c.chinaitlab.com/special/sjms/Index.html 一个月下来,把常见的20个设计模式好好复习并且逐个用C++实现了一遍,收获还是很大的,很多东西看上去明白 ...

  10. FCKeditor

    FCKeditor是一个专门使用在网页上属于开放源代码的所见即所得文字编辑器.它志于轻量化,不需要太复杂的安装步骤即可使用.     它可和PHP.JavaScript.ASP.ASP.NET.Col ...