13.多執行緒設計模式 - Future模式
阿新 • • 發佈:2018-11-20
多執行緒設計模式 - Future模式
併發設計模式屬於設計優化的一部分,它對於一些常用的多執行緒結構的總結和抽象。與序列相比並行程式結構通常較為複雜,因此合理的使用並行模式在多執行緒併發中更具有意義。
1. Future
Future模式是多執行緒開發中非常常見的一種設計模式,它的核心思想是非同步呼叫。
這類似我們日常生活中的線上購物流程,帶在購物網看著一件商品時可以提交表單,當訂單完成後就可以在家裡等待商品送貨上門。
或者說更形象的是我們傳送Ajax請求的時候,頁面是非同步的進行後臺處理,使用者無需等待請求的結果,可以繼續瀏覽或操作其他內容
示例:下面示例為Future的原理實現;<br />
說明:看類註釋即可明瞭 不明白可以去屎
1 //Data.java * 首先看這個介面Data,只有一個方法getRequest(),返回String字串. 2 public interface Data { 3 String getRequest(); 4 } 5 //RealData.java * 然後再看RealData這個類,實現了Data介面,首先他有建構函式,可以理解為一個真實的業務邏輯,比較耗時,做這個sleep我們可以想象成在處理業務邏輯. 6 public class RealData implements Data{ 7 privateString result; 8 9 public RealData(String queryStr){ 10 System.out.println("根據"+queryStr+"進行查詢,這是一個很耗時的操作.."); 11 try { 12 Thread.sleep(5000); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 System.out.println("操作完畢,獲取結果");17 result="查詢結果"; 18 } 19 20 @Override 21 public String getRequest() { 22 return result; 23 } 24 } 25 26 //FutureData.java* 接著再看FutureData這個類,也實現了Data介面.先看FutureData的getRequest()方法,這個方法先死迴圈判斷boolean,如果isReady是true,就阻塞著,不然就返回RealData真的getRequest()\\\方法(真實的結果). 27 // 然後再看setRealData(),判斷isReady,如果是ture,直接return,如果不是就賦值RealData,並修改isReady,然後notify().. 28 public class FutureData implements Data{ 29 30 private RealData realData; 31 private boolean isReady = false; 32 33 public synchronized void setRealData(RealData realData){ 34 //如果已經載入完畢就直接返回 35 if(isReady){ 36 return; 37 } 38 //如果沒有裝載,進行裝載真實物件 39 this.realData= realData; 40 isReady = true; 41 //進行通知 42 notify(); 43 } 44 45 @Override 46 public synchronized String getRequest() { 47 //如果沒有裝載好,程式就一直處於阻塞狀態 48 while(!isReady){ 49 try { 50 wait(); 51 } catch (InterruptedException e) { 52 e.printStackTrace(); 53 } 54 } 55 //裝載好直接獲取資料即可 56 return this.realData.getRequest(); 57 } 58 } 59 //FutureClient.java * 最後看FutureClient 這個類,最簡單了,返回futureData,偷偷開了執行緒,看到RealData realData = new RealData(request)沒有?就是開始執行業務了,然後當FutureData這個類的setRealData(RealData realData)時就通知了.. 60 public class FutureClient { 61 62 public Data request(final String queryStr){ 63 //1 我想要一個代理物件(Data介面的實現類)先返回傳送請求的客戶端,告訴他請求已經接收到,可以做其他事情 64 final FutureData futureData = new FutureData(); 65 //2 啟動一個新的執行緒,去載入真實的資料,傳遞給這個代理物件 66 new Thread(new Runnable(){ 67 @Override 68 public void run() { 69 //3 這個新的執行緒可以去慢慢載入真實物件,然後傳遞給代理物件 70 RealData realData = new RealData(queryStr); 71 futureData.setRealData(realData); 72 } 73 }).start(); 74 //直接返回一個假的包裝類futureData 75 return futureData; 76 } 77 } 78 //主函式 79 public class Main { 80 81 public static void main(String[] args) { 82 FutureClient fc = new FutureClient(); 83 Data data = fc.request("請求引數"); 84 System.out.println("請求傳送成功!"); 85 System.out.println("做其他的事情..."); 86 87 String result = data.getRequest(); 88 System.out.println(result); 89 } 90 }
上面的原理你可以不用懂,當然懂最好了,可以在面試官面前吹牛逼啊..future模式這麼凶殘,jdk也有實現的,在java.util.concurrent,又是concurrent,這個工具類真的是強大<br />
示例:<br />
1 // 2 import java.util.concurrent.Callable; 3 4 public class RealData implements Callable<String> { 5 private String Data; 6 7 public RealData(String Data) { 8 this.Data = Data; 9 } 10 11 public String call() throws Exception { 12 //利用sleep來表示任務處理 13 Thread.sleep(2000); 14 15 return "這是處理"+Data+"結果"; 16 } 17 } 18 // 19 import java.util.concurrent.ExecutorService; 20 import java.util.concurrent.Executors; 21 import java.util.concurrent.FutureTask; 22 23 public class Main { 24 25 public static void main(String[] args) throws Exception { 26 Long start = System.currentTimeMillis(); 27 28 FutureTask<String> futureTask = new FutureTask<>(new RealData("hello,world")); 29 ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(1); 30 newFixedThreadPool.submit(futureTask); 31 32 // 表示正在處理其他邏輯,或者業務 33 Thread.sleep(1000); 34 35 System.out.println("最後結果-->" + futureTask.get()); 36 37 Long end = System.currentTimeMillis(); 38 39 Long useTime = end - start; 40 41 System.out.println("程式運行了-->" + useTime + "毫秒"); 42 } 43 }