我愛學習網-上傳
當前位置: 主頁 > 文庫 > Java >

java-線程-多線程的設計模式

時間:2020-09-02 14:13來源:我愛學習網 作者:apple 點擊:

Future模式

先返回空殼數據,同時后臺啟動線程執行任務,當獲取數據時,使用wait方法進行阻塞,等待任務執行完畢,再進行返回真實數據

 

入口

 

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);
		
	}
}

 

對請求進行假數據響應

 

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

}

 

  • Master-Worker模式
  • 最常用的并行計算模式,系統由倆類進程協作進行工作,Master負責接收和分配任務,Worker負責處理子任務,當各個worker子進程處理完之后,會將結果返回給Master,由Master進行歸納和總結,將任務分解成若干個子任務,并行執行,從而提高系統的吞吐量

 

 

入口

 

import java.util.Random;

public class Main {

	public static void main(String[] args) {
		
		Master master = new Master(new Worker(), 20);
		
		Random r = new Random();
		for(int i = 1; i <= 100; i++){
			Task t = new Task();
			t.setId(i);
			t.setPrice(r.nextInt(1000));
			master.submit(t);
		}
		master.execute();
		long start = System.currentTimeMillis();
		
		while(true){
			if(master.isComplete()){
				long end = System.currentTimeMillis() - start;
				int priceResult = master.getResult();
				System.out.println("最終結果:" + priceResult + ", 執行時間:" + end);
				break;
			}
		}
		
	}
}

 

任務

 

public class Task {

	private int id;
	private int price ;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	} 
	
}

 

Master

 

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

public class Master {

	//1 有一個盛放任務的容器
	private ConcurrentLinkedQueue workQueue = new ConcurrentLinkedQueue();
	
	//2 需要有一個盛放worker的集合
	private HashMap workers = new HashMap();
	
	//3 需要有一個盛放每一個worker執行任務的結果集合 workers可能并發的提交結果集
	private ConcurrentHashMap resultMap = new ConcurrentHashMap();
	
	//4 構造方法
	public Master(Worker worker , int workerCount){
		worker.setWorkQueue(this.workQueue);
		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.workQueue.add(task);
	}
	
	//6 需要有一個執行的方法,啟動所有的worker方法去執行任務
	public void execute(){
		for(Map.Entry me : workers.entrySet()){
			me.getValue().start();
		}
	}

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

	//8 計算結果方法
	public int getResult() {
		int priceResult = 0;
		for(Map.Entry me : resultMap.entrySet()){
			priceResult += (Integer)me.getValue();
		}
		return priceResult;
	}

 

Worker

 

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

public class Worker implements Runnable {

	private ConcurrentLinkedQueue workQueue;
	private ConcurrentHashMap resultMap;
	
	public void setWorkQueue(ConcurrentLinkedQueue workQueue) {
		this.workQueue = workQueue;
	}

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

	private Object handle(Task input) {
		Object output = null;
		try {
			//處理任務的耗時。。 比如說進行操作數據庫。。。
			Thread.sleep(500);
			output = input.getPrice();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return output;
	}



}

 

  • 生產消費者模式

 

入口

 

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

public class Main {

	public static void main(String[] args) throws Exception {
		//內存緩沖區
		BlockingQueue queue = new LinkedBlockingQueue(10);
		//生產者
		Provider p1 = new Provider(queue);
		
		Provider p2 = new Provider(queue);
		Provider p3 = new Provider(queue);
		//消費者
		Consumer c1 = new Consumer(queue);
		Consumer c2 = new Consumer(queue);
		Consumer c3 = new Consumer(queue);
		//創建線程池運行,這是一個緩存的線程池,可以創建無窮大的線程,沒有任務的時候不創建線程。空閑線程存活時間為60s(默認值)

		ExecutorService cachePool = Executors.newCachedThreadPool();
		cachePool.execute(p1);
		cachePool.execute(p2);
		cachePool.execute(p3);
		cachePool.execute(c1);
		cachePool.execute(c2);
		cachePool.execute(c3);

		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		p1.stop();
		p2.stop();
		p3.stop();
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}		
//		cachePool.shutdown(); 
//		cachePool.shutdownNow();
		

	}
	
}

 

數據模型

 

public final class Data {

	private String id;
	private String name;
	
	public Data(String id, String name){
		this.id = id;
		this.name = name;
	}
	
	public String getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	@Override
	public String toString(){
		return "{id: " + id + ", name: " + name + "}";
	}
	
}

 

生產者

 

import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class Provider implements Runnable{
	
	//共享緩存區
	private BlockingQueue queue;
	//多線程間是否啟動變量,有強制從主內存中刷新的功能。即時返回線程的狀態
	private volatile boolean isRunning = true;
	//id生成器
	private static AtomicInteger count = new AtomicInteger();
	//隨機對象
	private static Random r = new Random(); 
	
	public Provider(BlockingQueue queue){
		this.queue = queue;
	}

	@Override
	public void run() {
		while(isRunning){
			try {
				//隨機休眠0 - 1000 毫秒 表示獲取數據(產生數據的耗時) 
				Thread.sleep(r.nextInt(1000));
				//獲取的數據進行累計...
				int id = count.incrementAndGet();
				//比如通過一個getData方法獲取了
				Data data = new Data(Integer.toString(id), "數據" + id);
				System.out.println("當前線程:" + Thread.currentThread().getName() + ", 獲取了數據,id為:" + id + ", 進行裝載到公共緩沖區中...");
				if(!this.queue.offer(data, 2, TimeUnit.SECONDS)){
					System.out.println("提交緩沖區數據失敗....");
					//do something... 比如重新提交
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void stop(){
		this.isRunning = false;
	}
	
}

 

消費者

 

import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

public class Consumer implements Runnable{

	private BlockingQueue queue;
	
	public Consumer(BlockingQueue queue){
		this.queue = queue;
	}
	
	//隨機對象
	private static Random r = new Random(); 

	@Override
	public void run() {
		while(true){
			try {
				//獲取數據
				Data data = this.queue.take();
				//進行數據處理。休眠0 - 1000毫秒模擬耗時
				Thread.sleep(r.nextInt(1000));
				System.out.println("當前消費線程:" + Thread.currentThread().getName() + ", 消費成功,消費數據為id: " + data.getId());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
------分隔線----------------------------
    ?分享到??
看看啦
主站蜘蛛池模板: 少妇激情一区二区三区视频| 成人影片一区免费观看| 一区二区三区四区在线视频| 老熟女五十路乱子交尾中出一区| 视频精品一区二区三区| 日韩免费一区二区三区在线| 国产亚洲一区二区手机在线观看| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 亚洲国模精品一区| 国模无码视频一区二区三区| 亚洲一区电影在线观看| 久久国产视频一区| 精品国产一区二区三区久久| 国产乱码精品一区二区三| 日本福利一区二区| 人妻互换精品一区二区| 色欲AV蜜桃一区二区三| 亚洲欧美国产国产一区二区三区| 亚洲无删减国产精品一区| 中文字幕无码一区二区免费| 久久久人妻精品无码一区| 一区二区三区在线看| 精品视频一区二区观看| 国产在线步兵一区二区三区| 国产精品成人99一区无码| 在线观看精品一区| 国产一区二区精品在线观看| 国产一区二区三区不卡在线观看 | 亚洲AV无码国产一区二区三区| 无码少妇一区二区三区 | 日韩一区二区三区视频久久| 国产日韩精品一区二区在线观看 | 亚洲国产精品第一区二区三区| 亚洲一区二区精品视频| 超清无码一区二区三区| 久久精品一区二区三区不卡| 蜜臀Av午夜一区二区三区| 精品国产鲁一鲁一区二区| 久久精品无码一区二区三区不卡 | 国产主播一区二区| 麻豆一区二区在我观看|