1.Future模式有點相似商品訂單。好比在網上進行購物,當看中某一件商品時,就能夠提交訂單。提交訂單完畢在家等候送貨上門。賣家根據訂單取貨、發貨,並配送到顧客手中。大部分狀況下,賣家處理訂單沒那麼快,可能須要幾天時間。而這段時間買家沒必要再家裏等候,能夠作其餘事情。 java
將此類推到程序設計中,當某一段程序提交了一個請求,指望獲得一個答覆。但很是不幸的是,服務程序對這個請求的處理可能很是慢。在傳統的單線程環境下,調用函數是同步的,也就是說它必需要等到服務程序返回結果後,纔可以進行其餘處理。而在Future模式下,調用方式該爲異步,而原來等待返回的時間段,在主調用函數中,則能夠用於處理其餘事物。傳統程序的調用流程以下圖所示。 多線程
圖1-1 傳統串行程序調用流程 併發
採用Future模式設計程序,調用流程以下。 app
圖1-2 Future模式流程圖 異步
表1-3 Future模式的主要參與者 ide
參與者 | 做用 |
Main | 系統啓動,調用Client發出請求你 |
Client | 返回Data對象,當即返回FutureData,並開啓ClientThread線程裝配RealData |
Data | 返回數據的接口 |
Future | Future數據,構造很快,可是是一個虛擬的數據,須要裝配RealData |
RealData | 真實數據,其構造是比較慢的 |
2.1Main函數的實現 函數
main函數主要負責調用Client發起請求,並使用返回的數據: this
public static void main(String[] args) { // TODO Auto-generated method stub Client client = new Client(); Data data = client.request("test"); System.out.println("----------------------------------"); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("----------------------------------"); System.out.println(data.getResult()); }
2.2Client的實現 spa
public class Client { public Data request(final String req_name) { FutureData fd = new FutureData(); new Thread() { @Override public void run() { // TODO Auto-generated method stub RealData rd = new RealData(req_name); fd.setRd(rd); }; }.start(); return fd; } }
2.3Data的實現 線程
public interface Data { public String getResult(); }
2.4FutureData的實現
FutureData實現了一個快速返回的RealData的包裝。是RealData的虛擬實現,所以它能夠快速的被構造返回。當使用FutureData的getResult()方法時,程序會阻塞,等待RealData被注入到程序中,才使用RealData的getResult()方法返回。
/** * packed the readdata * @author cosco * */ public class FutureData implements Data { protected RealData rd = null; protected volatile boolean isReady = false; public RealData getRd() { return rd; } public synchronized void setRd(RealData rd) { if(isReady){ return; } this.rd = rd; isReady = true; notifyAll(); } @Override public synchronized String getResult() { // TODO Auto-generated method stub while(!isReady){ try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return rd.getResult(); } }
2.5RealData的實現 RealData是最終須要使用的數據模型,它的構造很慢。在這裏,使用sleep()函數模擬這個過程:
package org.cosco.thread; /** * * @author cosco * */ public class RealData implements Data { private final String result; public RealData(String param){ StringBuffer sb = new StringBuffer(); for(int i = 0; i < 10; i++){ sb.append(param); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } result = sb.toString(); } @Override public String getResult() { // TODO Auto-generated method stub return result; } }
3.JDK的內置實現
Future模式比較經常使用,JDK的併發包中,就已經了一中Future模式的實現。JDK中實現的比較複雜,提供了更爲豐富的多線程控制功能。核心結構如圖:
圖3-1 JDK內置的Future模式
可使用JDK內置的Future模式實現咱們的功能,首先實現Callable接口,實現具體的業務邏輯。
import java.util.concurrent.Callable; public class RealData implements Callable<String>{ private String param; public RealData(String param){ this.param = param; } @Override public String call() throws Exception { // TODO Auto-generated method stub StringBuffer sb = new StringBuffer(); for(int i = 0; i < 10; i++){ sb.append(param); Thread.sleep(100); } return sb.toString(); } }
在這改進中,RealData的構造變得很是快,其業務邏輯被移到call()方法內,並經過call()方法返回。
main方法修改以下:
package testthread02; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; public class testmain { public static void main(String[] args) throws InterruptedException, ExecutionException { FutureTask<String> future = new FutureTask<String>(new RealData("a")); ExecutorService es = Executors.newFixedThreadPool(1); es.submit(future); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(future.get()); es.shutdown(); } }