核心思想
調用方式爲異步,去除了主函數中的等待時間,主函數可去處理其他任務,如圖:
代碼實現
參與者 | 作用 |
---|---|
Main | 主函數,調用Client發出請求 |
Client | 返回Data對象,立即返回FutureData,並開啓ClientThread線程裝配RealData |
Data | 返回數據的接口 |
FutureData | 虛擬數據,構造很快 |
RealData | 真實數據,構造較慢 |
代碼示意:
public static void main(String[] args)
{
Client client = new Client();
//立即返回,得到FutureData
Data data=client.request("name");
System.out.println("請求完畢");
//用sleep代表執行其他業務邏輯
Thread.sleep(2000);
//使用真實數據RealData
System.out.println(data.getResult());
}
//Data接口
public interface Data
{
public String getResult();
}
//Client類
public class Client
{
public Data request(String str)
{
FutureData fd = new FutureData();
//RealData構造很慢,單獨開線程構造
new Thread()
{
public void run()
{
RealData rd = new RealData(str);
fd.setRealData(rd);
}
}.start();
return fd;
}
}
//FutureData類
public class FutureData implements Data
{
//FutureData是對RealData的包裝
protected RealData rd = null;
protected boolean isReady=false;
public synchronized void setRealData(RealData rd)
{
if(isReady)
{
return;
}
this.rd=rd;
isReady=true;
notifyAll();
}
//會等待RealData構造完成
public synchronized String getResult()
{
while(!isReady)
{
//此類中可能有其他多線程任務,被喚醒的原因不一定是RealData構造完成,所以需要循環判斷isReady是否真的構造完成
wait();
}
return rd.getResult();
}
}
//RealData類
public class RealData implements Data
{
private String result=null;
public RealData()
{
//構造數據,假設很慢
result = new String("xxxxxx");
}
public String getResult()
{
return result;
}
}
JDK內置實現
想要異步執行的業務邏輯放在call()方法內
代碼示意:
public class RealData implements Callable<String>
{
private String para;
public RealData(String para)
{
this.para=para;
}
//真實業務邏輯
@Override
public String call()
{
//構造數據,假設很慢
return new String("xxxx");
}
}
public class Main
{
public static void main(String[] args)
{
FutureTask<String> future = new FutureTask<String>(new RealData("a"));
ExecutorService exe = Executors.newFixedThreadPool(1);
//開啓線程執行RealData的call()方法,相當於2中的client.request()
exe.submit(future);
System.out.println("請求完畢");
//用sleep代表執行其他業務邏輯
Thread.sleep(5000);
//使用真實數據,相當於2中的data.getResult(),如果call()沒有執行完,依然會等待
System.out.println(future.get());
}
}