Java多線程編程中Future模式的詳解<轉>


Java多線程編程中,常用的多線程設計模式包括:Future模式、Master-Worker模式、Guarded Suspeionsion模式、不變模式和生產者-消費者模式等。這篇文章主要講述Future模式,關於其他多線程設計模式的地址如下:
關於其他多線程設計模式的地址如下:
關於Master-Worker模式的詳解: Java多線程編程中Master-Worker模式的詳解
關於Guarded Suspeionsion模式的詳解: Java多線程編程中Guarded Suspeionsion模式的詳解
關於不變模式的詳解: Java多線程編程中不變模式的詳解
關於生產者-消費者模式的詳解:生產者-消費者模式Java詳解


1. Future模式核心思想

Future模式的核心在於:去除了主函數的等待時間,並使得原本需要等待的時間段可以用於處理其他業務邏輯(根據《Java程序性能優化》)。

Future模式有點類似於商品訂單。在網上購物時,提交訂單后,在收貨的這段時間里無需一直在家里等候,可以先干別的事情。類推到程序設計中時, 當提交請求時,期望得到答復時,如果這個答復可能很慢。傳統的時一直等待到這個答復收到時再去做別的事情,但如果利用Future設計模式就無需等待答復 的到來,在等待答復的過程中可以干其他事情。

例如如下的請求調用過程時序圖。當call請求發出時,需要很長的時間才能返回。左邊的圖需要一直等待,等返回數據后才能繼續其他操作;而右邊的 Future模式的圖中客戶端則無需等到可以做其他的事情。服務器段接收到請求后立即返回結果給客戶端,這個結果並不是真實的結果(是虛擬的結果),也就 是先獲得一個假數據,然后執行其他操作。

\

 


2. Future模式Java實現

Client的實現

Client主要完成的功能包括:1. 返回一個FutureData;2.開啟一個線程用於構造RealData。

public class Client {
	public Data request(final String string) {
		final FutureData futureData = new FutureData();
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				//RealData的構建很慢,所以放在單獨的線程中運行
				RealData realData = new RealData(string);
				futureData.setRealData(realData);
			}
		}).start();
		
		return futureData; //先直接返回FutureData
	}
}

Data的實現

無論是FutureData還是RealData都實現該接口。

public interface Data {
	String getResult() throws InterruptedException;
}

FutureData的實現

FutureData是Future模式的關鍵,它實際上是真實數據RealData的代理,封裝了獲取RealData的等待過程。

//FutureData是Future模式的關鍵,它實際上是真實數據RealData的代理,封裝了獲取RealData的等待過程
public class FutureData implements Data {
	RealData realData = null; //FutureData是RealData的封裝
	boolean isReady = false;  //是否已經准備好
	
	public synchronized void setRealData(RealData realData) {
		if(isReady)
			return;
		this.realData = realData;
		isReady = true;
		notifyAll(); //RealData已經被注入到FutureData中了,通知getResult()方法
	}

	@Override
	public synchronized String getResult() throws InterruptedException {
		if(!isReady) {
			wait(); //一直等到RealData注入到FutureData中
		}
		return realData.getResult(); 
	}
}

RealData的實現

RealData是最終需要使用的數據,它的構造函數很慢。

public class RealData implements Data {
	protected String data;

	public RealData(String data) {
		//利用sleep方法來表示RealData構造過程是非常緩慢的
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		this.data = data;
	}

	@Override
	public String getResult() {
		return data;
	}
}

測試運行

主函數主要負責調用Client發起請求,並使用返回的數據。

public class Application {
	public static void main(String[] args) throws InterruptedException {
		Client client = new Client();
		//這里會立即返回,因為獲取的是FutureData,而非RealData
		Data data = client.request("name");
		//這里可以用一個sleep代替對其他業務邏輯的處理
		//在處理這些業務邏輯過程中,RealData也正在創建,從而充分了利用等待時間
		Thread.sleep(2000);
		//使用真實數據
		System.out.println("數據="+data.getResult());
	}
}

 

3. Future模式的JDK內置實現

由於Future是非常常用的多線程設計模式,因此在JDK中內置了Future模式的實現。這些類在java.util.concurrent包 里面。其中最為重要的是FutureTask類,它實現了Runnable接口,作為單獨的線程運行。在其run()方法中,通過Sync內部類調用 Callable接口,並維護Callable接口的返回對象。當使用FutureTask.get()方法時,將返回Callable接口的返回對象。 同樣,針對上述的實例,如果使用JDK自帶的實現,則需要作如下調整。

首先,Data接口和FutureData就不需要了,JDK幫我們實現了。

其次,RealData改為這樣:

import java.util.concurrent.Callable;

public class RealData implements Callable {
	protected String data;

	public RealData(String data) {
		this.data = data;
	}

	@Override
	public String call() throws Exception {
		//利用sleep方法來表示真是業務是非常緩慢的
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return data;
	}
}

最后,在測試運行時,這樣調用:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class Application {
	public static void main(String[] args) throws Exception {
		FutureTask futureTask = 
				new FutureTask(new RealData("name"));
		ExecutorService executor = 
				Executors.newFixedThreadPool(1); //使用線程池
		//執行FutureTask,相當於上例中的client.request("name")發送請求
		executor.submit(futureTask);
		//這里可以用一個sleep代替對其他業務邏輯的處理
		//在處理這些業務邏輯過程中,RealData也正在創建,從而充分了利用等待時間
		Thread.sleep(2000);
		//使用真實數據
		//如果call()沒有執行完成依然會等待
		System.out.println("數據=" + futureTask.get());
	}
}

 

本文完。轉載請注明出處。

參考文獻
葛一鳴,Java程序性能優化.清華大學出版社.

轉自 http://www.2cto.com/kf/201411/351903.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM