02.第二階段、實戰Java高併發程式設計模式-6.併發設計模式
阿新 • • 發佈:2019-10-05
什麼是設計模式
單例模式
不變模式
Future模式
生產者消費者
-
什麼是設計模式
在軟體工程中,設計模式(design pattern)是對軟體設計中普遍存在(反覆出現)的各種問題 ,所提出的解決方案。這個術語是由埃裡希·伽瑪(Erich Gamma)等人在1990年代從建築設計領 域引入到電腦科學的。 Richard Helm, Ralph Johnson ,John Vlissides (Gof) 《設計模式:可複用面向物件軟體的基礎》 收錄 23種模式 – 觀察者模式 – 策略模式 – 裝飾者模式 – 享元模式 – 模板方法 架構模式 – MVC – 分層 設計模式 – 提煉系統中的元件 程式碼模式(成例 Idiom) – 低層次,與編碼直接相關 – 如DCL
-
單例模式
單例物件的類必須保證只有一個例項存在。許多時候整個系統只需要擁有一個的全域性物件,這樣 有利於我們協調系統整體的行為 比如:全域性資訊配置
/** * 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(); } }
-
不變模式
一個類的內部狀態建立後,在整個生命期間都不會發生變化時,就是不變類 不變模式不需要同步
/** * 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
-
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()); } }
-
生產者消費者模式
生產者-消費者模式是一個經典的多執行緒設計模式。它為多執行緒間的協作提供了良好的解決方案。 在生產者-消費者模式中,通常由兩類執行緒,即若干個生產者執行緒和若干個消費者執行緒。生產者線 程負責提交使用者請求,消費者執行緒則負責具體處理生產者提交的任務。生產者和消費者之間則通 過共享記憶體緩衝區進行通訊。
/** * 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