多線程設計模式之Future、Master-Worker和生產者-消費者模型

  並行設計模式屬於設計優化的一部分,它是對一些常用的多線程結構的總結和抽象。與串行程序相比,並行程序的結構通常更爲複雜。因此合理的使用並行模式在開發中更有意義,目前在開發中應用最多的是Future,Master-Woker和生產者-消費者模式
一、Future模式
  流程圖如下
在這裏插入圖片描述

public interface Data {

	String getRequest();

}

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 = "查詢結果";
	}
	
	@Override
	public String getRequest() {
		return result;
	}

}

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();
	}
	
	@Override
	public synchronized String getRequest() {
		//如果沒裝載好 程序就一直處於阻塞狀態
		while(!isReady){
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		//裝載好直接獲取數據即可
		return this.realData.getRequest();
	}


}
public class FutureClient {

	public Data request(final String queryStr){
		//1 我想要一個代理對象(Data接口的實現類)先返回給發送請求的客戶端,告訴他請求已經接收到,可以做其他的事情
		final FutureData futureData = new FutureData();
		//2 啓動一個新的線程,去加載真實的數據,傳遞給這個代理對象
		new Thread(new Runnable() {
			@Override
			public void run() {
				//3 這個新的線程可以去慢慢的加載真實對象,然後傳遞給代理對象
				RealData realData = new RealData(queryStr);
				futureData.setRealData(realData);
			}
		}).start();
		
		return futureData;
	}
	
}
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);
		
	}
}

一、Master-Woker模式
  Master-Woker模式是常用的並行計算模式。它的核心思想是系統由兩類進程協作工作:Master進程Worker進程。Master負責接收和分配任務,Worker負責處理子任務。當各個子進程處理完成之後,會將結果返回給Master,由Master做歸納和總結。好處是能夠將一個大任務分解成若干個小任務,並執行,從而提高系統的吞吐量。
在這裏插入圖片描述

public class Master_Join {
    // 1 有一個盛放任務的容器
    private ConcurrentLinkedQueue<Task> workQuen = new ConcurrentLinkedQueue<>();

    // 2 需要一個盛放worker的集合
    private Map<String,Thread> workers = new HashMap<String,Thread>();

    // 3 需要有一個盛放每一個worker執行任務的結果集合
    private ConcurrentHashMap<String,Object> resultMap = new ConcurrentHashMap<>();

    // 4 構造方法

    public Master_Join( Worker worker,int workerCount ){
         worker.setWorkQuen(this.workQuen);
         worker.setResultMap(this.resultMap);
        for (int i = 0; i < workerCount; i++) {
            this.workers.put(Integer.toString(i),new Thread(worker));

        }
    }
    // 5 需要一個提交任務的方法
    public void submit(Task task){
        this.workQuen.add(task);
    }
    // 6 需要有一個執行任務的方法,啓動所有的worker的方法並且執行
    public void execute(){
        for ( Map.Entry<String,Thread> worker :  workers.entrySet()){
                worker.getValue().start();
        }

    }
    // 7 判斷是否運行結束的方法
    public boolean isComplete(){
        for ( Map.Entry<String,Thread> worker :  workers.entrySet()){
           if(worker.getValue().getState() != Thread.State.TERMINATED){
               return  false;
           }
        }
        return  true;
    }

    // 8 獲得計算結果的方法
    public Double getResult(){
        Double priceResult = 0d;
        for(Map.Entry<String,Object> map : resultMap.entrySet()){
            priceResult +=(Double) map.getValue();
        }
        return priceResult;
    }

}
public class Task {
    private Long id;
    private String name;
    private double price;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}
public class Worker implements Runnable{
    private ConcurrentLinkedQueue<Task> workQuen;
    private ConcurrentHashMap<String,Object> resultMap;

    public void setWorkQuen(ConcurrentLinkedQueue<Task> workQuen) {
        this.workQuen = workQuen;
    }

    public void setResultMap(ConcurrentHashMap<String, Object> resultMap) {
        this.resultMap = resultMap;
    }


    @Override
    public void run() {
        while (true){
            Task input = this.workQuen.poll();
            if(null == input){
                break;
            }
            Object output = handle(input);
            this.resultMap.put(Long.toString(input.getId()),output);
        }
        

    }

    private Object handle(Task input) {
      return null;
    }

   /* private Object handle(Task input) {
        Object output = null;
        try {
            // 處理任務耗時。。。
            Thread.sleep(300);
            output = input.getPrice();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  output ;
    }*/

public class MyWorker  extends  Worker{
    private Object handle(Task input) {
        Object output = null;
        try {
            // 處理任務耗時。。。
            Thread.sleep(300);
            output = input.getPrice();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  output ;
    }
}
public class Main {
    public static void main(String[] args) {

        Master_Join master = new Master_Join(new Worker(),20);
        Random random  = new Random();

        for(long i = 0; i < 100; i++){
            Task task = new Task();
            task.setId(i);
            task.setPrice(random.nextInt(1500));
            master.submit(task);
        }

        master.execute();

        Instant instant = Instant.now();
        while (true){
            if(master.isComplete()){
                Instant  instant1 = Instant.now();
                Double result = master.getResult();
                long seconds = Duration.between(instant1, instant).getNano();
                System.out.println("最終結果:"+result+ "耗時:"+ seconds);
                break;
            }
        }


    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章