1. 程式人生 > >02.第二階段、實戰Java高併發程式設計模式-6.併發設計模式

02.第二階段、實戰Java高併發程式設計模式-6.併發設計模式

 什麼是設計模式 
 單例模式
 不變模式
 Future模式
 生產者消費者
  1. 什麼是設計模式

     在軟體工程中,設計模式(design pattern)是對軟體設計中普遍存在(反覆出現)的各種問題 ,所提出的解決方案。這個術語是由埃裡希·伽瑪(Erich Gamma)等人在1990年代從建築設計領 域引入到電腦科學的。
      Richard Helm, Ralph Johnson ,John Vlissides (Gof)
      《設計模式:可複用面向物件軟體的基礎》 收錄 23種模式
    
      – 觀察者模式
      – 策略模式
      – 裝飾者模式 – 享元模式
      – 模板方法
    
      架構模式 – MVC
     – 分層 
      設計模式
     – 提煉系統中的元件
      程式碼模式(成例 Idiom)
     – 低層次,與編碼直接相關 – 如DCL
    
  2. 單例模式

     單例物件的類必須保證只有一個例項存在。許多時候整個系統只需要擁有一個的全域性物件,這樣 有利於我們協調系統整體的行為
     比如:全域性資訊配置
    
    	/**
    	 * description: 餓漢式 執行緒安全
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: [email protected]
    	 * @email: [email protected]
    	 * @date: 2019/10/4    7:32 PM
    	 */
    	public class Singleton {
    		public static int STATUS = 1;
    
    		private Singleton() {
    			System.out.println("Singleton is create");
    		}
    
    		private static Singleton instance = new Singleton();
    
    		public static Singleton getInstance() {
    			return instance;
    		}
    
    		public static void main(String[] args) {
    			//何時產生例項 不好控制
    			System.out.println(Singleton.STATUS);
    			//輸出
    			// Singleton is create
    			//1
    		}
    
    
    	}
    
    	/**
    	 * description: 懶漢式 執行緒安全
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: [email protected]
    	 * @email: [email protected]
    	 * @date: 2019/10/4    7:37 PM
    	 */
    	public class LazySingleton {
    		//1.
    		private LazySingleton() {
    			System.out.println("LazySingleton is create");
    		}
    
    		private static LazySingleton instance = null;
    
    		public static synchronized LazySingleton getInstance() {
    			if (instance == null)
    				instance = new LazySingleton();
    			return instance;
    
    		}
    
    	//      2. 多執行緒 效能好
    	//    雙檢鎖/雙重校驗鎖(DCL,即 double-checked locking)執行緒安全
    	//    private volatile static LazySingleton instance;
    	//    private LazySingleton (){
    	//        System.out.println("LazySingleton is create");
    	//    }
    	//    public static LazySingleton getInstance() {
    	//        if (instance == null) {
    	//            synchronized (LazySingleton.class) {
    	//                if (instance == null) {
    	//                    instance = new LazySingleton();
    	//                }
    	//            }
    	//        }
    	//        return instance;
    	//    }
    
    		public static void main(String[] args) {
    			LazySingleton.getInstance();
    		}
    	}
    
    	/**
    	 * description: 靜態內部類 執行緒安全
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: [email protected]
    	 * @email: [email protected]
    	 * @date: 2019/10/4    7:39 PM
    	 */
    	public class StaticSingleton {
    		private StaticSingleton() {
    			System.out.println("StaticSingleton is create");
    		}
    
    		private static class SingletonHolder {
    			private static final StaticSingleton instance = new StaticSingleton();
    		}
    
    		public static final StaticSingleton getInstance() {
    			return SingletonHolder.instance;
    		}
    
    
    		public static void main(String[] args) {
    			StaticSingleton.getInstance();
    		}
    	}
    
  3. 不變模式

      一個類的內部狀態建立後,在整個生命期間都不會發生變化時,就是不變類 
      不變模式不需要同步
    
    	/**
    	 * description:
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: [email protected]
    	 * @email: [email protected]
    	 * @date: 2019/10/4    7:55 PM
    	 */
    	//確保無子類
    	public final class Product {
    		private final String no;
    		//私有屬性,不會被其他物件獲取
    		private final String name;
    		//final保證屬性不會被2次賦值
    		private final double price;
    
    		public Product(String no, String name, double price) {
    			super();
    			//因為建立之後,無法進行修改
    			this.no = no;
    			this.name = name;
    			this.price = price;
    		}
    
    		public String getNo() {
    			return no;
    		}
    
    		public String getName() {
    			return name;
    		}
    
    		public double getPrice() {
    			//在建立物件時,必須指定資料
    			return price;
    		}
    
    	}
    
      java.lang.String
      java.lang.Boolean 
      java.lang.Byte
      java.lang.Character 
      java.lang.Double
      java.lang.Float
      java.lang.Integer
      java.lang.Long
      java.lang.Short
    
  4. Future模式

    	/**
    	 * description:
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: [email protected]
    	 * @email: [email protected]
    	 * @date: 2019/10/4    8:07 PM
    	 */
    	public class RealData implements Data {
    		protected final String result;
    
    		public RealData(String para) {
    			//RealData的構造可能很慢,需要使用者等待很久,這裡使用sleep模擬
    			StringBuffer sb = new StringBuffer();
    			for (int i = 0; i < 10; i++) {
    				sb.append(para);
    				try {
    					//這裡使用sleep,代替一個很慢的操作過程
    					Thread.sleep(100);
    				} catch (InterruptedException e) {
    				}
    			}
    			result = sb.toString();
    		}
    
    		public String getResult() {
    			return result;
    		}
    	}
    
    	/**
    	 * description:
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: [email protected]
    	 * @email: [email protected]
    	 * @date: 2019/10/4    8:05 PM
    	 */
    	public class FutureData implements Data {
    		//FutureData是RealData的包裝
    
    		protected RealData realdata = null;
    		protected boolean isReady = false;
    
    		public synchronized void setRealData(RealData realdata) {
    			if (isReady) {
    				return;
    			}
    			this.realdata = realdata;
    			isReady = true;
    			//RealData已經被注入,通知getResult()
    			notifyAll();
    		}
    
    		//會等待RealData構造完成
    		public synchronized String getResult() {
    			while (!isReady) {
    				try {
    					//一直等待,知道RealData被注入
    
    					wait();
    				} catch (InterruptedException e) {
    				}
    			}
    			//由RealData實現
    			return realdata.result;
    		}
    	}
    
    	/**
    	 * description:
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: [email protected]
    	 * @email: [email protected]
    	 * @date: 2019/10/4    8:07 PM
    	 */
    	public class Client {
    		public Data request(final String queryStr) {
    			final FutureData future = new FutureData();
    			new Thread() {
    				// RealData的構建很慢,所以在單獨的執行緒中進行
    				public void run() {
    					RealData realdata = new RealData(queryStr);
    					future.setRealData(realdata);
    				}
    			}.start();
    			// FutureData會被立即返回
    			return future;
    		}
    
    		public static void main(String[] args) {
    
    			Client client = new Client();
    			//這裡會立即返回,因為得到的是FutureData而不是RealData
    			Data data = client.request("name");
    			System.out.println("請求完畢");
    			try {
    			//這裡可以用一個sleep代替了對其他業務邏輯的處理
    			//在處理這些業務邏輯的過程中,RealData被建立,從而充分利用了等待時間
    				Thread.sleep(2000);
    			} catch (InterruptedException e) {
    			}
    			//使用真實的資料
    			System.out.println("資料 = " + data.getResult());
    		}
    	}
    

    Callable 介面

    	import java.util.concurrent.Callable;
    
    	/**
    	 * description:
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: [email protected]
    	 * @email: [email protected]
    	 * @date: 2019/10/4    8:07 PM
    	 */
    	public class RealData implements Callable<String> {
    		protected final String para;
    
    		public RealData(String para) {
    
    			this.para = para;
    		}
    
    		@Override
    		public String call() throws Exception {
    			//RealData的構造可能很慢,需要使用者等待很久,這裡使用sleep模擬
    			StringBuffer sb = new StringBuffer();
    			for (int i = 0; i < 10; i++) {
    				sb.append(para);
    				try {
    					//這裡使用sleep,代替一個很慢的操作過程
    					Thread.sleep(100);
    				} catch (InterruptedException e) {
    				}
    			}
    			return sb.toString();
    		}
    	}
    
    	import java.util.concurrent.ExecutionException;
    	import java.util.concurrent.ExecutorService;
    	import java.util.concurrent.Executors;
    	import java.util.concurrent.Future;
    	import java.util.concurrent.FutureTask;
    
    	/**
    	 * description:
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: [email protected]
    	 * @email: [email protected]
    	 * @date: 2019/10/4    8:27 PM
    	 */
    	public class FutureMain {
    		public static void main(String[] args) throws InterruptedException, ExecutionException {
    			//1.
    	//        //構造FutureTask
    	//        FutureTask<String> future = new FutureTask<String>(new RealData("a"));
    	//        ExecutorService executor = Executors.newFixedThreadPool(1);
    	//        //執行FutureTask,相當於上例中的 client.request("a") 傳送請求
    	//        // 在這裡開啟執行緒進行RealData的call()執行
    	//        executor.submit(future);
    	//        executor.shutdown();
    	//        System.out.println("請求完畢");
    	//        try {
    	//            //這裡依然可以做額外的資料操作,這裡使用sleep代替其他業務邏輯的處理
    	//            Thread.sleep(2000);
    	//        } catch (InterruptedException e) {
    	//        }
    	//        //相當於data.getResult (),取得call()方法的返回值
    	//        // 如果此時call()方法沒有執行完成,則依然會等待
    	//        System.out.println("資料 = " + future.get());
    
    			//2.
    			ExecutorService executor = Executors.newFixedThreadPool(1);
    			//執行FutureTask,相當於上例中的 client.request("a") 傳送請求
    			// 在這裡開啟執行緒進行RealData的call()執行
    			Future<String> future = executor.submit(new RealData("a"));
    			System.out.println("請求完畢");
    			try { //這裡依然可以做額外的資料操作,這裡使用sleep代替其他業務邏輯的處理
    				Thread.sleep(2000);
    			} catch (InterruptedException e) {
    			}
    			//相當於data.getResult (),取得call()方法的返回值
    			// 如果此時call()方法沒有執行完成,則依然會等待
    			System.out.println("資料 = " + future.get());
    		}
    
    	}
    
  5. 生產者消費者模式

     生產者-消費者模式是一個經典的多執行緒設計模式。它為多執行緒間的協作提供了良好的解決方案。 在生產者-消費者模式中,通常由兩類執行緒,即若干個生產者執行緒和若干個消費者執行緒。生產者線 程負責提交使用者請求,消費者執行緒則負責具體處理生產者提交的任務。生產者和消費者之間則通 過共享記憶體緩衝區進行通訊。
    

    	/**
    	 * description:
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: [email protected]
    	 * @email: [email protected]
    	 * @date: 2019/10/4    10:32 PM
    	 */
    	public final class PCData {
    		private final int intData;
    
    		public PCData(int intData) {
    			this.intData = intData;
    		}
    
    		public PCData(String d) {
    			this.intData = Integer.valueOf(d);
    		}
    
    		public int getIntData() {
    			return intData;
    		}
    
    		@Override
    		public String toString() {
    			return "data:" + intData;
    		}
    	}
    
    	import java.util.Random;
    	import java.util.concurrent.BlockingQueue;
    	import java.util.concurrent.TimeUnit;
    	import java.util.concurrent.atomic.AtomicInteger;
    
    	/**
    	 * description:
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: [email protected]
    	 * @email: [email protected]
    	 * @date: 2019/10/3    10:05 PM
    	 */
    	public class Producer implements Runnable{
    
    		private volatile boolean isRunning = true;
    		private BlockingQueue<PCData> queue;
    		private static AtomicInteger count = new AtomicInteger();
    		private static final int SLEEPTIME = 1000;
    
    		public Producer(BlockingQueue<PCData> queue) {
    			this.queue = queue;
    		}
    
    		@Override
    		public void run() {
    			PCData data = null;
    			Random r = new Random();
    			System.out.println("start producer id=" + Thread.currentThread().getId());
    			try {
    				while (isRunning) {
    					Thread.sleep(r.nextInt(SLEEPTIME));
    					data = new PCData(count.incrementAndGet());
    					System.out.println(data + " is put into queue");
    					if (!queue.offer(data,2, TimeUnit.SECONDS)) {
    						System.out.println("failed to put data: " + data);
    					}
    				}
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    				Thread.currentThread().interrupt();
    			}
    		}
    		public void stop() {
    			isRunning = false;
    		}
    	}
    
    	import java.text.MessageFormat;
    	import java.util.Random;
    	import java.util.concurrent.BlockingQueue;
    
    	/**
    	 * description:
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: [email protected]
    	 * @email: [email protected]
    	 * @date: 2019/10/3    10:05 PM
    	 */
    	public class Consumer implements Runnable{
    
    		private BlockingQueue<PCData> queue;
    		private static final int SLEEPTIME = 1000;
    
    		public Consumer(BlockingQueue<PCData> queue) {
    			this.queue = queue;
    		}
    
    		@Override
    		public void run() {
    			System.out.println("start Consumer id=" + Thread.currentThread().getId());
    			Random r = new Random();
    			try {
    				while (true) {
    					PCData data = queue.take();
    					if (null != data) {
    						int re = data.getIntData() * data.getIntData();
    						System.out.println(MessageFormat.format("{0}*{1}={2}",data.getIntData(),data.getIntData(),re));
    						Thread.sleep(r.nextInt(SLEEPTIME));
    					}
    				}
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    				Thread.currentThread().interrupt();
    			}
    		}
    	}
    
    	/**
    	 * description:
    	 *
    	 * @author: dawn.he QQ:       905845006
    	 * @email: [email protected]
    	 * @email: [email protected]
    	 * @date: 2019/10/4    10:19 PM
    	 */
    	import java.util.concurrent.BlockingQueue;
    	import java.util.concurrent.ExecutorService;
    	import java.util.concurrent.Executors;
    	import java.util.concurrent.LinkedBlockingQueue;
    
    	public class Storage {
    
    		// 倉庫儲存的載體
    		private LinkedBlockingQueue<Object> list = new LinkedBlockingQueue<>(10);
    
    		public void produce() {
    			try{
    				list.put(new Object());
    				System.out.println("【生產者" + Thread.currentThread().getName()
    						+ "】生產一個產品,現庫存" + list.size());
    			} catch (InterruptedException e){
    				e.printStackTrace();
    			}
    		}
    
    		public void consume() {
    			try{
    				list.take();
    				System.out.println("【消費者" + Thread.currentThread().getName()
    						+ "】消費了一個產品,現庫存" + list.size());
    			} catch (InterruptedException e){
    				e.printStackTrace();
    			}
    		}
    
    		public static void main(String[] args) throws InterruptedException {
    	//       Storage storage =  new Storage();
    	//        storage.produce();
    	//        storage.consume();
    
    				BlockingQueue<PCData> queue = new LinkedBlockingQueue<>(10);
    				Producer producer1 = new Producer(queue);
    				Producer producer2 = new Producer(queue);
    				Producer producer3 = new Producer(queue);
    				Consumer consumer1 = new Consumer(queue);
    				Consumer consumer2 = new Consumer(queue);
    				Consumer consumer3 = new Consumer(queue);
    				ExecutorService service = Executors.newCachedThreadPool();
    				service.execute(producer1);
    				service.execute(producer2);
    				service.execute(producer3);
    				service.execute(consumer1);
    				service.execute(consumer2);
    				service.execute(consumer3);
    				Thread.sleep(10 * 1000);
    				producer1.stop();
    				producer2.stop();
    				producer3.stop();
    				Thread.sleep(3000);
    				service.shutdown();
    		}
    	}
    

從BlockingQueue到無鎖Disruptor的效能提升:https://blog.csdn.net/weixin_33704591/article