轉載:http://blog.csdn.net/lmdcszh/article/details/39696357
多線程開發可以更好的發揮多核cpu性能,常用的多線程設計模式有:Future、Master-Worker、Guard Susperionsion、不變、生產者-消費者 模式;jdk除了定義了若干併發的數據結構,也內置了多線程框架和各種線程池; 鎖(分爲內部鎖、重入鎖、讀寫鎖)、ThreadLocal、信號量等在併發控制中發揮着巨大的作用。這裏重點介紹第一種併發——Future模型。
一、什麼是Future模型:
該模型是將異步請求和代理模式聯合的模型產物。類似商品訂單模型。見下圖:
客戶端發送一個長時間的請求,服務端不需等待該數據處理完成便立即返回一個僞造的代理數據(相當於商品訂單,不是商品本身),用戶也無需等待,先去執行其他的若干操作後,再去調用服務器已經完成組裝的真實數據。該模型充分利用了等待的時間片段。
二、Future模式的核心結構:
Main:啓動系統,調用Client發出請求;
Client:返回Data對象,理解返回FutureData,並開啓ClientThread線程裝配RealData;
Data:返回數據的接口;
FutureData:Future數據,構造很快,但是是一個虛擬的數據,需要裝配RealData;
RealData:真實數據,構造比較慢。
三、Future模式的代碼實現:
(1)Main函數:
- <span style="font-size:18px;">package tgb;
- public class Main {
- public static void main(String[] args){
- Client client = new Client();
- //理解返回一個FutureData
- Data data = client.request("name");
- System.out.println("請求完畢!");
- try{
- //處理其他業務
- //這個過程中,真是數據RealData組裝完成,重複利用等待時間
- Thread.sleep(2000);
- }catch (Exception e){
- }
- //真實數據
- System.out.println("數據 = "+ data.getResult());
- }
- }
- </span>
(2)Client的實現:
- <span style="font-size:18px;">package tgb;
- public class Client {
- public Data request(final String queryStr){
- final FutureData future = new FutureData();
- //開啓一個新的線程來構造真實數據
- new Thread(){
- public void run(){
- RealData realData = new RealData(queryStr);
- future.setRealData(realData); }
- }.start();
- return future;
- }
- }
- </span>
(3)Data的實現:
- <span style="font-size:18px;">package tgb;
- public interface Data {
- public String getResult();
- }
- </span>
(4)FutureData:
- <span style="font-size:18px;">package tgb;
- /**
- * 是對RealData的一個包裝
- * @author limin
- *
- */
- public class FutureData implements Data {
- protected RealData realData =null;
- protected boolean isReady = false;
- public synchronized void setRealData(RealData realData){
- if(isReady){
- return;
- }
- this.realData=realData;
- isReady=true;
- notifyAll();
- }
- @Override
- public synchronized String getResult() {
- while(!isReady){
- try{
- wait();
- }catch (Exception e){
- }
- }
- return realData.result;
- }
- }
- </span>
(5)RealData實現:
- <span style="font-size:18px;">package tgb;
- public class RealData implements Data {
- protected String result;
- public RealData(String para){
- //構造比較慢
- StringBuffer sb= new StringBuffer();
- for(int i=0;i<10;i++){
- sb.append(para);
- try{
- Thread.sleep(1000);
- }catch(Exception e){
- }
- result= sb.toString();
- }
- }
- @Override
- public String getResult() {
- return result;
- }
- }
- </span>
注意:
FutureData是對RealData的包裝,是dui真實數據的一個代理,封裝了獲取真實數據的等待過程。它們都實現了共同的接口,所以,針對客戶端程序組是沒有區別的;
客戶端在調用的方法中,單獨啓用一個線程來完成真實數據的組織,這對調用客戶端的main函數式封閉的;
因爲咋FutureData中的notifyAll和wait函數,主程序會等待組裝完成後再會繼續主進程,也就是如果沒有組裝完成,main函數會一直等待。