Future三重奏第一章:Future設計模式及程式碼示例
Future系列文章
Future模式的作用
去除等待主函式執行某項耗時操作的等待時間,在執行主函式耗時業務操作的時候,及時返回一個數據,繼續主函式剩下的業務,當需要獲取之前耗時操作的結果的時候在進行獲取
其本質則是在維持主業務順利進行的同時,非同步的執行主業務中的耗時分業務,使得原本需要進行等待的時間可以處理其他的業務
###實際業務場景: 在開具電子發票的業務中,當我們申請開電子發票的時候,電子發票並不會立即開票成功,而是需要調取第三方介面,第三方介面在返回告訴我們是否開具成功,這時候需要等待一段時間才能得到開票結果,在等待第三方返回結果的同時,這個時候我們還有其他別的業務要進行處理返回,不可能一直等待第三方返回的資料,這時候我們就可以採用future模式,將該方法改為非同步處理,在等待資料返回的時候進行其他業務的處理
future模式核心類作用
此處通過幾個簡單的類來展示future模式的思路和執行方式 Main類:系統啟動類,呼叫Client類發出業務請求 Client類:該類在接收到構造並返回FutureData類,返回的FutureData類是一個虛假的物件,或者說並不是一個擁有實際資料的物件,Client的核心在於構建一個新的執行緒去執行RealData類,該類是處理耗時的業務類 Data:獲取實際資料的介面,futureData類和realData類需要實現該介面 FutureData類:及時返回呼叫類,內部封裝了實際資料,可通過該類獲取實際的業務資料 RealData:實際的業務處理類,耗時較長
future模式示例程式碼
Main類
發起請求,構建執行了Client類,返回了Data物件,並在最後呼叫了data物件實際獲取到的資料
public class Main { public static void main(String args[]){ Client client=new Client(); //呼叫client傳送請求 Data data=client.request("Hello Future!"); System.out.println("請求完畢!"); try { //模擬處理其他業務 Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } //呼叫實際返回的資料 System.out.println("真實資料:" + data.getResult()); } }
Data介面
Main類中實際返回Data物件,該介面提供獲取資料的方法
public interface Data {
String getResult();
}
Client類
在主類中構建的Client類,並返回futureData物件,另一方面通過該類生成執行緒發出非同步請求,新執行緒中執行業務類,並返回計算結果,將計算結果封裝進futureData物件中
public class Client {
public Data request(String param){
//立即返回futureData
FutureData futureData=new FutureData();
//需要啟動一個新執行緒
//開啟ClientThread執行緒裝配realData
new Thread(() -> {
//裝配realData
//RealData為業務類,傳遞相關引數過去
RealData realData=new RealData(param);
//獲取到資料後將資料封裝進實體類中
futureData.setRealData(realData);
}).start();
return futureData;
}
}
RealData類
實際業務類,該類主要是執行業務方法並得到計算結果,並提供獲取資料的方法
public class RealData implements Data{
private String result;//封裝實際資料
/**
* 獲取計算結果方法
* @return
*/
@Override
public String getResult() {
return result;
}
public RealData(String param){
StringBuffer sb=new StringBuffer();
sb.append(param);
//模擬業務執行
//此處通過執行緒睡眠的方式
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//獲取真實資料result,等待再次獲取資料
result=sb.toString();
}
}
FutureData類
在client的呼叫中,會首先返回一個空的futuredata物件,然後啟動一個新的執行緒去執行業務類獲取資料,在獲取資料後,會將獲取的資料封裝進futuredata類中,所以,futuredata類相應的提供了封裝實際資料的方法。當你需要獲取實際資料當時候,如果尚未獲取資料成功,則進入等待佇列
public class FutureData implements Data {
private RealData realData;
private boolean isReady=false;//如果已經獲取資料此處為true
private ReentrantLock lock=new ReentrantLock();
private Condition condition=lock.newCondition();
/**
* 獲取實際資料
* @return
*/
@Override
public String getResult()
{
//如果尚未成功獲取資料,則當前執行緒加入等待佇列
while (!isReady){
try {
lock.lock();
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
return realData.getResult();
}
public void setRealData(RealData realData){
lock.lock();
if (isReady){
return;
}
//裝載實際資料物件
this.realData = realData;
isReady = true;
condition.signal();
lock.unlock();
}
}
以上就是future設計模式的簡單實現,future模式線上程池的實現中有很大的體現,在第二章中我會詳細介紹jdk中futuretask的詳細實現,線上程池模組中也會對futureTask的使用作出詳細介紹