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 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!