JAVA多執行緒之Future模式
阿新 • • 發佈:2019-02-13
Future模式有點類似於商品訂單。比如在網購時,當看中某一個商品時,就可以提交訂單,當訂單處理完成後,在家裡等待商品送貨上門即可。或者說更形象的我們傳送Ajax請求的時候,頁面是非同步的進行後臺處理,使用者無需一直等待請求的結果,可繼續瀏覽或操作其他內容。
下面看一個例子:
1.客戶端傳送請求
客戶端傳送請求,包裝類返回“假”的結果,同時建立一個執行緒去執行真實的操作。
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class FutureDemo { public static void main(String[] args) throws InterruptedException, ExecutionException { //假設這裡在計算一個結果要花5秒鐘,我們就可以起一個執行緒讓他計算,在計算期間我們可以幹別的事情。 Callable<Integer> call = new Callable<Integer>() { public Integer call() throws Exception { System.out.println("正在計算結果"); Thread.sleep(5000); return 1; }; }; //把call交給FutureTask FutureTask<Integer> task = new FutureTask<>(call); //開啟執行緒去執行計算任務 Thread t = new Thread(task); t.start(); //在這期間,我們可以乾點別的 Thread.sleep(10); System.out.println("乾點別的"); //幹完之後,等計算完成,在愛拿到結果 Integer result = task.get(); System.out.println("拿到的結果為:"+result); } }
下面,我們模擬一個場景,實現Future模式。 假設,現在你要去麵包店去買一塊蛋糕,但是,生產一塊蛋糕要花一段時間,你總不能一直等下去,這個時候,你可以先去上班,等下班回來之後,你再去取蛋糕。 我們就實現這麼一個場景:
public class FutureClient { public Data request(final String queryStr){ //1 我想要一個代理物件(Data介面的實現類)先返回給傳送請求的客戶端,告訴他請求已經接收到,可以做其他的事情 final FutureData futureData = new FutureData(); //2 啟動一個新的執行緒,去載入真實的資料,傳遞給這個代理物件 new Thread(new Runnable() { public void run() { //3 這個新的執行緒可以去慢慢的載入真實物件,然後傳遞給代理物件 RealData realData = new RealData(queryStr); futureData.setRealData(realData); } }).start(); return futureData; } }
2.包裝類操作
package com.thread.mythread.conn015;
public interface Data {
String getRequest();
}
public class FutureData implements Data{ private RealData realData ; private boolean isReady = false; public synchronized void setRealData(RealData realData) { //如果已經裝載完畢了,就直接返回 if(isReady){ return; } //如果沒裝載,進行裝載真實物件 this.realData = realData; isReady = true; //進行通知 notify(); } public synchronized String getRequest() { //如果沒裝載好 程式就一直處於阻塞狀態 while(!isReady){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //裝載好直接獲取資料即可 return this.realData.getRequest(); } }
3.真實結果
public class RealData implements Data{
private String result ;
public RealData (String queryStr){
System.out.println("根據" + queryStr + "進行查詢,這是一個很耗時的操作..");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("操作完畢,獲取結果");
result = "查詢結果";
}
public String getRequest() {
return result;
}
}
4、執行測試
package com.thread.mythread.conn015;
public class Main {
public static void main(String[] args) throws InterruptedException {
FutureClient fc = new FutureClient();
Data data = fc.request("請求引數");
System.out.println("請求傳送成功!");
System.out.println("做其他的事情...");
String result = data.getRequest();
System.out.println(result);
}
}
5、列印結果
請求傳送成功!
做其他的事情…
根據請求引數進行查詢,這是一個很耗時的操作..
操作完畢,獲取結果
查詢結果