併發編程-Future模式

1.Future模式有點相似商品訂單。好比在網上進行購物,當看中某一件商品時,就能夠提交訂單。提交訂單完畢在家等候送貨上門。賣家根據訂單取貨、發貨,並配送到顧客手中。大部分狀況下,賣家處理訂單沒那麼快,可能須要幾天時間。而這段時間買家沒必要再家裏等候,能夠作其餘事情。 java

將此類推到程序設計中,當某一段程序提交了一個請求,指望獲得一個答覆。但很是不幸的是,服務程序對這個請求的處理可能很是慢。在傳統的單線程環境下,調用函數是同步的,也就是說它必需要等到服務程序返回結果後,纔可以進行其餘處理。而在Future模式下,調用方式該爲異步,而原來等待返回的時間段,在主調用函數中,則能夠用於處理其餘事物。傳統程序的調用流程以下圖所示。 多線程

                                        圖1-1 傳統串行程序調用流程 併發

採用Future模式設計程序,調用流程以下。 app

                                        圖1-2 Future模式流程圖 異步

                                        表1-3 Future模式的主要參與者 ide


參與者 做用
Main 系統啓動,調用Client發出請求你
Client 返回Data對象,當即返回FutureData,並開啓ClientThread線程裝配RealData
Data 返回數據的接口
Future Future數據,構造很快,可是是一個虛擬的數據,須要裝配RealData
RealData 真實數據,其構造是比較慢的

2.Future模式的代碼實現

2.1Main函數的實現 函數

    main函數主要負責調用Client發起請求,並使用返回的數據: this


public static void main(String[] args) {
// TODO Auto-generated method stub


    Client client = new Client();
    Data data = client.request("test");
    System.out.println("----------------------------------");

    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    System.out.println("----------------------------------");
    System.out.println(data.getResult());

}

2.2Client的實現 spa

public class Client {


    public Data request(final String req_name) {

        FutureData fd = new FutureData();

        new Thread() {
        @Override
        public void run() {
        // TODO Auto-generated method stub

        RealData rd = new RealData(req_name);
        fd.setRd(rd);
    
        };
        }.start();

        return fd;

    }
}

2.3Data的實現 線程

public interface Data {


    public String getResult();

}

2.4FutureData的實現

    FutureData實現了一個快速返回的RealData的包裝。是RealData的虛擬實現,所以它能夠快速的被構造返回。當使用FutureData的getResult()方法時,程序會阻塞,等待RealData被注入到程序中,才使用RealData的getResult()方法返回。

/**
 * packed the readdata
 * @author cosco
 *
 */
public class FutureData implements Data {

protected RealData rd = null;

    protected volatile boolean  isReady  = false;

    public RealData getRd() {
        return rd;
    }




    public synchronized void setRd(RealData rd) {

        if(isReady){
            return;
        }

        this.rd = rd;

        isReady = true;

        notifyAll();

    }




    @Override
    public synchronized String getResult() {
    // TODO Auto-generated method stub
    while(!isReady){
    try {
        wait();
       } catch (InterruptedException e) {
    // TODO Auto-generated catch block
        e.printStackTrace();
        }
    }

    return rd.getResult();
    }


}


2.5RealData的實現

    RealData是最終須要使用的數據模型,它的構造很慢。在這裏,使用sleep()函數模擬這個過程:


package org.cosco.thread;

/**
 * 
 * @author cosco
 *
 */
public class RealData implements Data {
	
	private final String result;

	public RealData(String param){
		StringBuffer sb = new StringBuffer();
		for(int i = 0; i < 10; i++){
			sb.append(param);
			
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
			
		result = sb.toString();
	}
	
	@Override
	public  String getResult() {
		// TODO Auto-generated method stub
		
		return result;
	}

}





3.JDK的內置實現

Future模式比較經常使用,JDK的併發包中,就已經了一中Future模式的實現。JDK中實現的比較複雜,提供了更爲豐富的多線程控制功能。核心結構如圖:


                                                圖3-1 JDK內置的Future模式

可使用JDK內置的Future模式實現咱們的功能,首先實現Callable接口,實現具體的業務邏輯。


import java.util.concurrent.Callable;

public class RealData implements Callable<String>{
	
	private String param;
	
	public RealData(String param){
		this.param = param;
	}
	
	
	@Override
	public String call() throws Exception {
		// TODO Auto-generated method stub
		
		StringBuffer sb = new StringBuffer();
		
		for(int i = 0; i < 10; i++){
			sb.append(param);
			
			Thread.sleep(100);
			
		}
		return sb.toString();
	}

}

    在這改進中,RealData的構造變得很是快,其業務邏輯被移到call()方法內,並經過call()方法返回。

main方法修改以下:

package testthread02;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class testmain {

	public static void main(String[] args) throws InterruptedException, ExecutionException {

		FutureTask<String> future = new FutureTask<String>(new RealData("a"));

		ExecutorService es = Executors.newFixedThreadPool(1);

		es.submit(future);

		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		System.out.println(future.get());

		es.shutdown();

	}

}
相關文章
相關標籤/搜索