Java 併發專題 :FutureTask 實現預加載數據 在線看電子書、瀏覽器瀏覽網頁等

FutureTask 有點相似Runnable,均可以經過Thread來啓動,不過FutureTask能夠返回執行完畢的數據,而且FutureTask的get方法支持阻塞。java

因爲:FutureTask能夠返回執行完畢的數據,而且FutureTask的get方法支持阻塞這兩個特性,咱們能夠用來預先加載一些可能用到資源,而後要用的時候,調用get方法獲取(若是資源加載完,直接返回;不然繼續等待其加載完成)。網絡

下面經過兩個例子來介紹下:異步

一、使用FutureTask來預加載稍後要用的的數據。ide

 

package com.jhaso.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() + ":加載資源結束");
	}

}


運行結果:this

 

 

1400902789275:開始加載資源
加載資源須要3秒
1400902790275:加載資源結束

能夠看到,原本加載資源的時間須要3秒,如今只花費了1秒,若是用戶其餘操做時間更長,則可直接返回,極大增長了用戶體驗。線程

 

二、看下Future的API資源

能夠看到Future的API,仍是比簡單的,見名知意的感受,get( long , TimeUnit )還能支持,設置最大等待時間,好比某個操做耗時太長,就能夠取消了。get

三、FutureTask模擬,用戶在線觀看電子書的預加載功能it

用戶觀看當前頁時,後臺預先把下一頁加載好,這樣能夠大幅度提升用戶的體驗,不須要每一頁都等待加載,用戶會以爲此電子書軟件很流暢,哈哈,用戶以爲好,纔是真的好。io

 

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的應用場景,,,請勿直接在項目中使用。

相關文章
相關標籤/搜索