一、單例模式
-
java設計模式分為三大類,創建型,結構型,行為型
-
裝飾器屬于結構型
-
單例模式屬于創建型
-
單例模式要求某個類的實體在整個應用中只能有一個,實體只能由本類來創建,實體在多執行緒情況下必須是執行緒安全的,
-
在應用中,如果需要某個類的實體只能有一個,比如整個應用都要對同一 個檔案進行讀寫,多個執行緒要操作同一個變數,多個執行緒要使用同一個連接物件來操作資料庫,
-
spring 中的 Bean 默認都是單例的,
-
單例可以節約資源,一是物件的創建只有一 次,節省記憶體,節省創建和銷毀的時間,
-
單例模式的設計原則,必須在類中具有三個要素:
- 需要一個靜態的屬于本類的成員變數,
- 構造方法必須是私有的,保證只能在內部創建物件,
- 需要一個靜態的方法,創建物件并回傳物件,保證在沒有物件的前提下,可以創建唯一物件并回傳物件,
-
設計形式:
-
懶漢型,包括執行緒安全與非執行緒安全(加鎖,用 synchronized 或可重入鎖)只建議單執行緒情況下使用,不加鎖,(使用時才創建)
package com.zhong.test_6; public class Lazy { private static Lazy lazy;//懶漢型 private Lazy() {} public static Lazy getInstance() { if (lazy == null) lazy = new Lazy(); return lazy; } } -
餓漢型,是執行緒安全的,初始化時就創建物件,(可能存在浪費資源問題)
package com.zhong.test_6; public class Hungry { private static Lazy lazy = new Lazy();//餓漢型 private Lazy() {} public static Lazy getInstance() { return lazy; } } -
雙檢鎖型,主要用在多執行緒并發的情況下,并且效率很高,也不會出現資源浪費情況,多執行緒下最建議使用的,
package com.zhong.test_6; public class DoubleCheckLock { private static DoubleCheckLock obj; private DoubleCheckLock() {} public static DoubleCheckLock getInstance() { if (obj == null) synchronized (DoubleCheckLock.class) { if (obj == null) { obj = new DoubleCheckLock(); } } return obj; } } -
用列舉型別
二、設計模式——工廠模式
- 工廠是越來生產產品的,不同的工廠生產不同的產品,
- java 中的工廠設計模式,是創建物件的最佳方式,它屬于創建型模式,
- 好處在于,可以隱藏創建物件的邏輯,物件的使用只需要告訴對方我要什么物件就可以了,
- 工廠模式主要應用于物件的創建等比較繁瑣的情形,
- 使用工廠模式,必須回傳介面型別,
三、執行緒池
- 現代的服務器都是多 cpu,執行緒采用多執行緒的方式來進行設計,可以更好的利用計算機的資源,如果不考慮多cpu多核的情況,單純的多執行緒并不會提高程式的執行效率,相反還會降低效率,在多執行緒執行的情形下,需要創建執行緒,銷毀執行緒,切換執行緒等,執行緒越多,堆疊區的記憶體消耗也越多,所以效率不會提高還會下降,
-
為什么還要使用執行緒池
- 在多執行緒并發作業的前提下,如果需要的執行緒資料比較大,需要執行緒完成的任務比較多,勢必就會產生大量的創建執行緒,銷毀執行緒,切換執行緒的額外的作業,這會讓系統的效率急劇下降,也容易造成記憶體泄露,執行緒池的出現,很好地解決了這個問題,執行緒池也是 jdk1.5 的新特性,在應用程式開始運行時,一次性創建一定數量的執行緒,把他們放在池中,如果有任務到達,不需要再去創建執行緒,直接從池中取出執行緒讓它去執行當前的任務,任務執行完畢,執行緒仍會回到池中,可以重復使用,應用程式結束前,把執行緒池銷毀,執行緒池可以極大的提高執行緒的復用率,
-
執行緒池的結構
-
有人認為執行緒池是一個框架,是 jdk 提供的更好利用多執行緒來進行作業的一個基礎框架,
-
執行緒池基于一種特定的結構,利用它可以更好地對多執行緒進行有效的管理,并能夠最大限度的節約資源,提升效率,
-
Interface Executor 執行緒池的基礎介面,提供一個 execute() 方法來執行執行緒的任務,
-
public interface ExecutorService extends Executor
- submit(Runnable task) 該方法執行執行緒執行目標(任務),底層呼叫了 execute()
- shutdown() 關閉執行緒池
-
public abstract class AbstractExecutorService extends Object implements ExecutorService 實作了 submit方法
-
public class ThreadPoolExecutor extends AbstractExecutorService
- 這是實作執行緒池功能最主要的類,該類的物件就是一個執行緒池,
- 它有四個構造方法,構造方法的引數最多有七個,利用這些構造方法可以創建具有功能不同,特性不同的各自執行緒池,前三個構造方法都是呼叫第四個構造方法來創建執行緒池,
-
執行緒池的幾個主要要素:
- 池中執行緒的數量
- 空閑執行緒的生存時間,可以調整池的作業效率
- 任務佇列,可分為有界和無界佇列兩種,有界表示佇列中元素的數量是有限的,無界則沒有限制,
- 執行緒工廠,執行緒包含兩種,一種是沒有回傳值的執行緒(比如Runnable),另外一種有回傳值且可以拋例外(Call),
-
public class Executors extends Object
- 提供了多種工廠方法,來創建不同特性種類的執行緒池,如果程式中需要創建執行緒池,也就是需要使用執行緒池,可以通過該類的工廠方法類得到執行緒池物件,該類就是工廠類,
-
執行緒池的使用場景
- 框架,web 應用服務器
package com.zhong.test_9; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolDemo { public static void main(String[] args) { // ExecutorService pool1 = Executors.newFixedThreadPool(2); ExecutorService pool1 = Executors.newCachedThreadPool(); pool1.submit((Runnable) () -> { while (true) { try { Thread.sleep(500); System.out.println("一邊吃飯"); } catch (InterruptedException e) { e.printStackTrace(); } } }); pool1.submit((Runnable) () -> { while (true) { try { Thread.sleep(500); System.out.println("一邊聽歌"); } catch (InterruptedException e) { e.printStackTrace(); } } }); pool1.submit((Runnable) () -> { while (true) { try { Thread.sleep(500); System.out.println("一邊聊天"); } catch (InterruptedException e) { e.printStackTrace(); } } }); try { Thread.sleep(2000); // pool1.shutdownNow();//要求沒有活動任務時才能關閉 } catch (InterruptedException e) { e.printStackTrace(); } } }
-
-
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/260714.html
標籤:其他
下一篇:[系統安全] 二十二.PE數字簽名之(下)微軟證書漏洞CVE-2020-0601復現及Windows驗證機制分析
