Java 并發專題 :FutureTask 實現預加載數據 在線看電子書、瀏覽器瀏覽網頁等
繼續并發專題~
FutureTask 有點類似Runnable,都可以通過Thread來啟動,不過FutureTask可以返回執行完畢的數據,并且FutureTask的get方法支持阻塞。
由于:FutureTask可以返回執行完畢的數據,并且FutureTask的get方法支持阻塞這兩個特性,我們可以用來預先加載一些可能用到資源,然后要用的時候,調用get方法獲取(如果資源加載完,直接返回;否則繼續等待其加載完成)。
下面通過兩個例子來介紹下:
1、使用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 PreLoaderUseFutureTask
{
/**
* 創建一個FutureTask用來加載資源
*/
private final FutureTask<String> futureTask = new FutureTask<String>(
new Callable<String>()
{
@Override
public String call() throws Exception
{
Thread.sleep(3000);
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(2000);
/**
* 獲取資源
*/
System.out.println(System.currentTimeMillis() + ":開始加載資源");
String res = task.getRes();
System.out.println(res);
System.out.println(System.currentTimeMillis() + ":加載資源結束");
}
} 運行結果:
1400902789275:開始加載資源 加載資源需要3秒 1400902790275:加載資源結束可以看到,本來加載資源的時間需要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 = 1;
/**
* 異步的任務獲取當前頁的內容
*/
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 + 1;
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(1000);
return "Page " + this.currentPage + " : the content ....";
}
public static void main(String[] args) throws InterruptedException,
ExecutionException
{
BookInstance instance = new BookInstance(1);
for (int i = 0; i < 10; i++)
{
long start = System.currentTimeMillis();
String content = instance.getCurrentPageContent();
System.out.println("[1秒閱讀時間]read:" + content);
Thread.sleep(1000);
System.out.println(System.currentTimeMillis() - start);
}
}
} 輸出結果:
[1秒閱讀時間]read:Page 1 : the content .... 2001 [1秒閱讀時間]read:Page 2 : the content .... 1000 [1秒閱讀時間]read:Page 3 : the content .... 1001 [1秒閱讀時間]read:Page 4 : the content .... 1000 [1秒閱讀時間]read:Page 5 : the content .... 1001
可以看到,除了第一次觀看當前頁需要等待網絡加載數據的過程(輸出的:2001,1000是加載耗時,1000是用戶閱讀時間),接下來的頁面都是瞬間返回(輸出的1000是用戶閱讀時間),完全不需要等待。
代碼都是為了講解FutureTask的應用場景,,,請勿直接在項目中使用。
好了,就到這里,歡迎各位留言。
來自: http://blog.csdn.net//lmj623565791/article/details/26817403
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!